PR432215 Add debuginfod functionality
[valgrind.git] / coregrind / m_debuginfo / readelf.c
blob3f5f48c7033f3adfe4c05ceafa9ae83cd8bc9bce
2 /*--------------------------------------------------------------------*/
3 /*--- Reading of syms & debug info from ELF .so/executable files. ---*/
4 /*--- readelf.c ---*/
5 /*--------------------------------------------------------------------*/
7 /*
8 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
11 Copyright (C) 2000-2017 Julian Seward
12 jseward@acm.org
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.
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.
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, see <http://www.gnu.org/licenses/>.
27 The GNU General Public License is contained in the file COPYING.
30 #if defined(VGO_linux) || defined(VGO_solaris)
32 #include "pub_core_basics.h"
33 #include "pub_core_vki.h"
34 #include "pub_core_vkiscnums.h"
35 #include "pub_core_debuginfo.h"
36 #include "pub_core_libcbase.h"
37 #include "pub_core_libcprint.h"
38 #include "pub_core_libcassert.h"
39 #include "pub_core_libcfile.h"
40 #include "pub_core_libcproc.h"
41 #include "pub_core_machine.h" /* VG_ELF_CLASS */
42 #include "pub_core_options.h"
43 #include "pub_core_oset.h"
44 #include "pub_core_pathscan.h" /* find_executable */
45 #include "pub_core_syscall.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_image.h"
50 #include "priv_d3basics.h"
51 #include "priv_tytypes.h"
52 #include "priv_storage.h"
53 #include "priv_readelf.h" /* self */
54 #include "priv_readdwarf.h" /* 'cos ELF contains DWARF */
55 #include "priv_readdwarf3.h"
56 #include "priv_readexidx.h"
57 #include "config.h"
59 /* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
60 #include <elf.h>
61 #if defined(VGO_solaris)
62 #include <sys/link.h> /* ElfXX_Dyn, DT_* */
63 #endif
64 /* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
66 #if !defined(HAVE_ELF32_CHDR)
67 typedef struct {
68 Elf32_Word ch_type;
69 Elf32_Word ch_size;
70 Elf32_Word ch_addralign;
71 } Elf32_Chdr;
72 #endif
74 #if !defined(HAVE_ELF64_CHDR)
75 typedef struct {
76 Elf64_Word ch_type;
77 Elf64_Word ch_reserved;
78 Elf64_Xword ch_size;
79 Elf64_Xword ch_addralign;
80 } Elf64_Chdr;
81 #endif
83 #if !defined(SHF_COMPRESSED)
84 #define SHF_COMPRESSED (1 << 11)
85 #endif
87 #if !defined(ELFCOMPRESS_ZLIB)
88 #define ELFCOMPRESS_ZLIB 1
89 #endif
91 #define SIZE_OF_ZLIB_HEADER 12
93 /*------------------------------------------------------------*/
94 /*--- 32/64-bit parameterisation ---*/
95 /*------------------------------------------------------------*/
97 /* For all the ELF macros and types which specify '32' or '64',
98 select the correct variant for this platform and give it
99 an 'XX' name. Then use the 'XX' variant consistently in
100 the rest of this file.
102 #if VG_WORDSIZE == 4
103 # define ElfXX_Ehdr Elf32_Ehdr
104 # define ElfXX_Shdr Elf32_Shdr
105 # define ElfXX_Phdr Elf32_Phdr
106 # define ElfXX_Nhdr Elf32_Nhdr
107 # define ElfXX_Sym Elf32_Sym
108 # define ElfXX_Off Elf32_Off
109 # define ElfXX_Word Elf32_Word
110 # define ElfXX_Addr Elf32_Addr
111 # define ElfXX_Dyn Elf32_Dyn
112 # define ELFXX_ST_BIND ELF32_ST_BIND
113 # define ELFXX_ST_TYPE ELF32_ST_TYPE
114 # define ElfXX_Chdr Elf32_Chdr
116 #elif VG_WORDSIZE == 8
117 # define ElfXX_Ehdr Elf64_Ehdr
118 # define ElfXX_Shdr Elf64_Shdr
119 # define ElfXX_Phdr Elf64_Phdr
120 # define ElfXX_Nhdr Elf64_Nhdr
121 # define ElfXX_Sym Elf64_Sym
122 # define ElfXX_Off Elf64_Off
123 # define ElfXX_Word Elf64_Word
124 # define ElfXX_Addr Elf64_Addr
125 # define ElfXX_Dyn Elf64_Dyn
126 # define ELFXX_ST_BIND ELF64_ST_BIND
127 # define ELFXX_ST_TYPE ELF64_ST_TYPE
128 # define ElfXX_Chdr Elf64_Chdr
130 #else
131 # error "VG_WORDSIZE should be 4 or 8"
132 #endif
135 /*------------------------------------------------------------*/
136 /*--- ---*/
137 /*--- Read symbol table and line info from ELF files. ---*/
138 /*--- ---*/
139 /*------------------------------------------------------------*/
141 /* readelf.c parses ELF files and acquires symbol table info from
142 them. It calls onwards to readdwarf.c to read DWARF2/3 line number
143 and call frame info found. */
145 /* Identify an ELF object file by peering at the first few bytes of
146 it. */
148 Bool ML_(is_elf_object_file)( const void* image, SizeT n_image, Bool rel_ok )
150 const ElfXX_Ehdr* ehdr = image;
151 Int ok = 1;
153 if (n_image < sizeof(ElfXX_Ehdr))
154 return False;
156 ok &= (ehdr->e_ident[EI_MAG0] == 0x7F
157 && ehdr->e_ident[EI_MAG1] == 'E'
158 && ehdr->e_ident[EI_MAG2] == 'L'
159 && ehdr->e_ident[EI_MAG3] == 'F');
160 ok &= (ehdr->e_ident[EI_CLASS] == VG_ELF_CLASS
161 && ehdr->e_ident[EI_DATA] == VG_ELF_DATA2XXX
162 && ehdr->e_ident[EI_VERSION] == EV_CURRENT);
163 ok &= (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN
164 || (rel_ok && ehdr->e_type == ET_REL));
165 ok &= (ehdr->e_machine == VG_ELF_MACHINE);
166 ok &= (ehdr->e_version == EV_CURRENT);
167 ok &= (ehdr->e_shstrndx != SHN_UNDEF);
168 ok &= (ehdr->e_shoff != 0 && ehdr->e_shnum != 0);
169 ok &= ((ehdr->e_phoff != 0 && ehdr->e_phnum != 0)
170 || ehdr->e_type == ET_REL);
172 return ok ? True : False;
176 /* The same thing, but operating on a DiImage instead. */
178 static Bool is_elf_object_file_by_DiImage( DiImage* img, Bool rel_ok )
180 /* Be sure this doesn't make the frame too big. */
181 vg_assert(sizeof(ElfXX_Ehdr) <= 512);
183 ElfXX_Ehdr ehdr;
184 if (!ML_(img_valid)(img, 0, sizeof(ehdr)))
185 return False;
187 ML_(img_get)(&ehdr, img, 0, sizeof(ehdr));
188 return ML_(is_elf_object_file)( &ehdr, sizeof(ehdr), rel_ok );
192 /* Show a raw ELF symbol, given its in-image address and name. */
194 static
195 void show_raw_elf_symbol ( DiImage* strtab_img,
196 Int i,
197 const ElfXX_Sym* sym,
198 DiOffT sym_name_ioff, Addr sym_svma,
199 Bool ppc64_linux_format )
201 const HChar* space = ppc64_linux_format ? " " : "";
202 VG_(printf)("raw symbol [%4d]: ", i);
203 switch (ELFXX_ST_BIND(sym->st_info)) {
204 case STB_LOCAL: VG_(printf)("LOC "); break;
205 case STB_GLOBAL: VG_(printf)("GLO "); break;
206 case STB_WEAK: VG_(printf)("WEA "); break;
207 case STB_LOPROC: VG_(printf)("lop "); break;
208 case STB_HIPROC: VG_(printf)("hip "); break;
209 default: VG_(printf)("??? "); break;
211 switch (ELFXX_ST_TYPE(sym->st_info)) {
212 case STT_NOTYPE: VG_(printf)("NOT "); break;
213 case STT_OBJECT: VG_(printf)("OBJ "); break;
214 case STT_FUNC: VG_(printf)("FUN "); break;
215 case STT_SECTION: VG_(printf)("SEC "); break;
216 case STT_FILE: VG_(printf)("FIL "); break;
217 case STT_LOPROC: VG_(printf)("lop "); break;
218 case STT_HIPROC: VG_(printf)("hip "); break;
219 default: VG_(printf)("??? "); break;
221 HChar* sym_name = NULL;
222 if (sym->st_name)
223 sym_name = ML_(img_strdup)(strtab_img, "di.sres.1", sym_name_ioff);
224 VG_(printf)(": svma %#010lx, %ssz %4llu %s\n",
225 sym_svma, space, (ULong)(sym->st_size + 0UL),
226 (sym_name ? sym_name : "NONAME") );
227 if (sym_name)
228 ML_(dinfo_free)(sym_name);
232 /* Decide whether SYM is something we should collect, and if so, copy
233 relevant info to the _OUT arguments. For {x86,amd64,ppc32}-linux
234 this is straightforward - the name, address, size are copied out
235 unchanged.
237 There is a bit of a kludge re data symbols (see KLUDGED BSS CHECK
238 below): we assume that the .bss is mapped immediately after .data,
239 and so accept any data symbol which exists in the range [start of
240 .data, size of .data + size of .bss). I don't know if this is
241 really correct/justifiable, or not.
243 For ppc64be-linux it's more complex. If the symbol is seen to be in
244 the .opd section, it is taken to be a function descriptor, and so
245 a dereference is attempted, in order to get hold of the real entry
246 point address. Also as part of the dereference, there is an attempt
247 to calculate the TOC pointer (R2 value) associated with the symbol.
249 To support the ppc64be-linux pre-"dotless" ABI (prior to gcc 4.0.0),
250 if the symbol is seen to be outside the .opd section and its name
251 starts with a dot, an .opd deference is not attempted, and no TOC
252 pointer is calculated, but the leading dot is removed from the
253 name.
255 As a result, on ppc64be-linux, the caller of this function may have
256 to piece together the real size, address, name of the symbol from
257 multiple calls to this function. Ugly and confusing.
259 static
260 Bool get_elf_symbol_info (
261 /* INPUTS */
262 struct _DebugInfo* di, /* containing DebugInfo */
263 const ElfXX_Sym* sym, /* ELF symbol */
264 DiOffT sym_name_ioff, /* name, may be absent (DiOffT_INVALID) */
265 const DiSlice* escn_strtab, /* holds the name */
266 Addr sym_svma, /* address as stated in the object file */
267 Bool symtab_in_debug, /* symbol table is in the debug file */
268 const DiSlice* escn_opd, /* the .opd (ppc64be-linux only) */
269 PtrdiffT opd_bias, /* for biasing AVMAs found in .opd */
270 /* OUTPUTS */
271 DiOffT* sym_name_out_ioff, /* name (in strtab) we should record */
272 SymAVMAs* sym_avmas_out, /* sym avmas we should record */
273 Int* sym_size_out, /* symbol size */
274 Bool* from_opd_out, /* ppc64be-linux only: did we deref an
275 .opd entry? */
276 Bool* is_text_out, /* is this a text symbol? */
277 Bool* is_ifunc_out, /* is this a STT_GNU_IFUNC function ?*/
278 Bool* is_global_out /* is this a global symbol ?*/
281 Bool plausible;
282 # if defined(VGP_ppc64be_linux)
283 Bool is_in_opd;
284 # endif
285 Bool in_text, in_data, in_sdata, in_rodata, in_bss, in_sbss;
286 Addr text_svma, data_svma, sdata_svma, rodata_svma, bss_svma, sbss_svma;
287 PtrdiffT text_bias, data_bias, sdata_bias, rodata_bias, bss_bias, sbss_bias;
288 # if defined(VGPV_arm_linux_android) \
289 || defined(VGPV_x86_linux_android) \
290 || defined(VGPV_mips32_linux_android) \
291 || defined(VGPV_arm64_linux_android)
292 Addr available_size = 0;
293 #define COMPUTE_AVAILABLE_SIZE(segsvma, segsize) \
294 available_size = segsvma + segsize - sym_svma
295 #else
296 #define COMPUTE_AVAILABLE_SIZE(segsvma, segsize)
297 #endif
299 /* Set defaults */
300 *sym_name_out_ioff = sym_name_ioff;
301 (*sym_avmas_out).main = sym_svma; /* we will bias this shortly */
302 *is_text_out = True;
303 SET_TOCPTR_AVMA(*sym_avmas_out, 0); /* default to unknown/inapplicable */
304 SET_LOCAL_EP_AVMA(*sym_avmas_out, 0); /* default to unknown/inapplicable */
305 *from_opd_out = False;
306 *is_ifunc_out = False;
307 *is_global_out = False;
309 /* Get the symbol size, but restrict it to fit in a signed 32 bit
310 int. Also, deal with the stupid case of negative size by making
311 the size be 1. Note that sym->st_size has type UWord,
312 effectively. */
313 { Word size_tmp = (Word)sym->st_size;
314 Word max_Int = (1LL << 31) - 1;
315 if (size_tmp < 0) size_tmp = 1;
316 if (size_tmp > max_Int) size_tmp = max_Int;
317 *sym_size_out = (Int)size_tmp;
319 /* After this point refer only to *sym_size_out and not to
320 sym->st_size. */
322 /* Figure out if we're interested in the symbol. Firstly, is it of
323 the right flavour? */
324 plausible
325 = (ELFXX_ST_BIND(sym->st_info) == STB_GLOBAL
326 || ELFXX_ST_BIND(sym->st_info) == STB_LOCAL
327 || ELFXX_ST_BIND(sym->st_info) == STB_WEAK
330 (ELFXX_ST_TYPE(sym->st_info) == STT_FUNC
331 || ELFXX_ST_TYPE(sym->st_info) == STT_OBJECT
332 # ifdef STT_GNU_IFUNC
333 || ELFXX_ST_TYPE(sym->st_info) == STT_GNU_IFUNC
334 # endif
337 /* Work out the svma and bias for each section as it will appear in
338 addresses in the symbol table. */
339 if (symtab_in_debug) {
340 text_svma = di->text_debug_svma;
341 text_bias = di->text_debug_bias;
342 data_svma = di->data_debug_svma;
343 data_bias = di->data_debug_bias;
344 sdata_svma = di->sdata_debug_svma;
345 sdata_bias = di->sdata_debug_bias;
346 rodata_svma = di->rodata_debug_svma;
347 rodata_bias = di->rodata_debug_bias;
348 bss_svma = di->bss_debug_svma;
349 bss_bias = di->bss_debug_bias;
350 sbss_svma = di->sbss_debug_svma;
351 sbss_bias = di->sbss_debug_bias;
352 } else {
353 text_svma = di->text_svma;
354 text_bias = di->text_bias;
355 data_svma = di->data_svma;
356 data_bias = di->data_bias;
357 sdata_svma = di->sdata_svma;
358 sdata_bias = di->sdata_bias;
359 rodata_svma = di->rodata_svma;
360 rodata_bias = di->rodata_bias;
361 bss_svma = di->bss_svma;
362 bss_bias = di->bss_bias;
363 sbss_svma = di->sbss_svma;
364 sbss_bias = di->sbss_bias;
367 /* Now bias (*sym_avmas_out).main accordingly by figuring out exactly which
368 section the symbol is from and bias accordingly. Screws up if
369 the previously deduced section svma address ranges are wrong. */
370 if (di->text_present
371 && di->text_size > 0
372 && sym_svma >= text_svma
373 && sym_svma < text_svma + di->text_size) {
374 *is_text_out = True;
375 (*sym_avmas_out).main += text_bias;
376 COMPUTE_AVAILABLE_SIZE(text_svma, di->text_size);
377 } else
378 if (di->data_present
379 && di->data_size > 0
380 && sym_svma >= data_svma
381 && sym_svma < data_svma + di->data_size) {
382 *is_text_out = False;
383 (*sym_avmas_out).main += data_bias;
384 COMPUTE_AVAILABLE_SIZE(data_svma, di->data_size);
385 } else
386 if (di->sdata_present
387 && di->sdata_size > 0
388 && sym_svma >= sdata_svma
389 && sym_svma < sdata_svma + di->sdata_size) {
390 *is_text_out = False;
391 (*sym_avmas_out).main += sdata_bias;
392 COMPUTE_AVAILABLE_SIZE(sdata_svma, di->sdata_size);
393 } else
394 if (di->rodata_present
395 && di->rodata_size > 0
396 && sym_svma >= rodata_svma
397 && sym_svma < rodata_svma + di->rodata_size) {
398 *is_text_out = False;
399 (*sym_avmas_out).main += rodata_bias;
400 COMPUTE_AVAILABLE_SIZE(rodata_svma, di->rodata_size);
401 } else
402 if (di->bss_present
403 && di->bss_size > 0
404 && sym_svma >= bss_svma
405 && sym_svma < bss_svma + di->bss_size) {
406 *is_text_out = False;
407 (*sym_avmas_out).main += bss_bias;
408 COMPUTE_AVAILABLE_SIZE(bss_svma, di->bss_size);
409 } else
410 if (di->sbss_present
411 && di->sbss_size > 0
412 && sym_svma >= sbss_svma
413 && sym_svma < sbss_svma + di->sbss_size) {
414 *is_text_out = False;
415 (*sym_avmas_out).main += sbss_bias;
416 COMPUTE_AVAILABLE_SIZE(sbss_svma, di->sbss_size);
417 } else {
418 /* Assume it's in .text. Is this a good idea? */
419 *is_text_out = True;
420 (*sym_avmas_out).main += text_bias;
423 # ifdef STT_GNU_IFUNC
424 /* Check for indirect functions. */
425 if (*is_text_out
426 && ELFXX_ST_TYPE(sym->st_info) == STT_GNU_IFUNC) {
427 *is_ifunc_out = True;
429 # endif
431 if (ELFXX_ST_BIND(sym->st_info) == STB_GLOBAL) {
432 *is_global_out = True;
435 # if defined(VGP_ppc64be_linux)
436 /* Allow STT_NOTYPE in the very special case where we're running on
437 ppc64be-linux and the symbol is one which the .opd-chasing hack
438 below will chase. */
439 if (!plausible
440 && *is_text_out
441 && ELFXX_ST_TYPE(sym->st_info) == STT_NOTYPE
442 && *sym_size_out > 0
443 && di->opd_present
444 && di->opd_size > 0
445 && (*sym_avmas_out).main >= di->opd_avma
446 && (*sym_avmas_out).main < di->opd_avma + di->opd_size)
447 plausible = True;
448 # endif
450 if (!plausible)
451 return False;
453 /* Ignore if nameless. */
454 if (sym_name_ioff == DiOffT_INVALID
455 || /* VG_(strlen)(sym_name) == 0 */
456 /* equivalent but cheaper ... */
457 ML_(img_get_UChar)(escn_strtab->img, sym_name_ioff) == '\0') {
458 if (TRACE_SYMTAB_ENABLED) {
459 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
460 "di.gesi.1", sym_name_ioff);
461 TRACE_SYMTAB(" ignore -- nameless: %s\n", sym_name);
462 if (sym_name) ML_(dinfo_free)(sym_name);
464 return False;
467 /* Ignore if zero-sized. Except on Android:
469 On Android 2.3.5, some of the symbols that Memcheck needs to
470 intercept (for noise reduction purposes) have zero size, due to
471 lack of .size directives in handwritten assembly sources. So we
472 can't reject them out of hand -- instead give them a bogusly
473 large size and let canonicaliseSymtab trim them so they don't
474 overlap any following symbols. At least the following symbols
475 are known to be affected:
477 in /system/lib/libc.so: strlen strcmp strcpy memcmp memcpy
478 in /system/bin/linker: __dl_strcmp __dl_strlen
480 if (*sym_size_out == 0) {
481 # if defined(VGPV_arm_linux_android) \
482 || defined(VGPV_x86_linux_android) \
483 || defined(VGPV_mips32_linux_android) \
484 || defined(VGPV_arm64_linux_android)
485 *sym_size_out = available_size ? available_size : 2048;
486 # else
487 if (TRACE_SYMTAB_ENABLED) {
488 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
489 "di.gesi.2", sym_name_ioff);
490 TRACE_SYMTAB(" ignore -- size=0: %s\n", sym_name);
491 if (sym_name) ML_(dinfo_free)(sym_name);
493 return False;
494 # endif
497 /* This seems to significantly reduce the number of junk
498 symbols, and particularly reduces the number of
499 overlapping address ranges. Don't ask me why ... */
500 if ((Int)sym->st_value == 0) {
501 if (TRACE_SYMTAB_ENABLED) {
502 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
503 "di.gesi.3", sym_name_ioff);
504 TRACE_SYMTAB( " ignore -- valu=0: %s\n", sym_name);
505 if (sym_name) ML_(dinfo_free)(sym_name);
507 return False;
510 /* If it's apparently in a GOT or PLT, it's really a reference to a
511 symbol defined elsewhere, so ignore it. */
512 if (di->got_present
513 && di->got_size > 0
514 && (*sym_avmas_out).main >= di->got_avma
515 && (*sym_avmas_out).main < di->got_avma + di->got_size) {
516 if (TRACE_SYMTAB_ENABLED) {
517 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
518 "di.gesi.4", sym_name_ioff);
519 TRACE_SYMTAB(" ignore -- in GOT: %s\n", sym_name);
520 if (sym_name) ML_(dinfo_free)(sym_name);
522 return False;
524 if (di->plt_present
525 && di->plt_size > 0
526 && (*sym_avmas_out).main >= di->plt_avma
527 && (*sym_avmas_out).main < di->plt_avma + di->plt_size) {
528 if (TRACE_SYMTAB_ENABLED) {
529 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
530 "di.gesi.5", sym_name_ioff);
531 TRACE_SYMTAB(" ignore -- in PLT: %s\n", sym_name);
532 if (sym_name) ML_(dinfo_free)(sym_name);
534 return False;
537 /* ppc64be-linux nasty hack: if the symbol is in an .opd section,
538 then really what we have is the address of a function
539 descriptor. So use the first word of that as the function's
540 text.
542 See thread starting at
543 http://gcc.gnu.org/ml/gcc-patches/2004-08/msg00557.html
545 # if defined(VGP_ppc64be_linux)
546 /* Host and guest may have different Endianness, used by BE only */
547 is_in_opd = False;
548 # endif
550 if (di->opd_present
551 && di->opd_size > 0
552 && (*sym_avmas_out).main >= di->opd_avma
553 && (*sym_avmas_out).main < di->opd_avma + di->opd_size) {
554 # if !defined(VGP_ppc64be_linux)
555 if (TRACE_SYMTAB_ENABLED) {
556 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
557 "di.gesi.6", sym_name_ioff);
558 TRACE_SYMTAB(" ignore -- in OPD: %s\n", sym_name);
559 if (sym_name) ML_(dinfo_free)(sym_name);
561 return False;
562 # else
563 Int offset_in_opd;
564 Bool details = 1||False;
566 if (details)
567 TRACE_SYMTAB("opdXXX: opd_bias %p, sym_svma_out %p\n",
568 (void*)(opd_bias), (void*)(*sym_avmas_out).main);
570 if (!VG_IS_8_ALIGNED((*sym_avmas_out).main)) {
571 if (TRACE_SYMTAB_ENABLED) {
572 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
573 "di.gesi.6a", sym_name_ioff);
574 TRACE_SYMTAB(" ignore -- not 8-aligned: %s\n", sym_name);
575 if (sym_name) ML_(dinfo_free)(sym_name);
577 return False;
580 /* (*sym_avmas_out).main is a avma pointing into the .opd section. We
581 know the vma of the opd section start, so we can figure out
582 how far into the opd section this is. */
584 offset_in_opd = (Addr)(*sym_avmas_out).main - (Addr)(di->opd_avma);
585 if (offset_in_opd < 0 || offset_in_opd >= di->opd_size) {
586 if (TRACE_SYMTAB_ENABLED) {
587 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
588 "di.gesi.6a", sym_name_ioff);
589 TRACE_SYMTAB(" ignore -- invalid OPD offset: %s\n", sym_name);
590 if (sym_name) ML_(dinfo_free)(sym_name);
592 return False;
595 /* Now we want to know what's at that offset in the .opd
596 section. We can't look in the running image since it won't
597 necessarily have been mapped. But we can consult the oimage.
598 opd_img is the start address of the .opd in the oimage.
599 Hence: */
601 ULong fn_descr[2]; /* is actually 3 words, but we need only 2 */
602 if (!ML_(img_valid)(escn_opd->img, escn_opd->ioff + offset_in_opd,
603 sizeof(fn_descr))) {
604 if (TRACE_SYMTAB_ENABLED) {
605 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
606 "di.gesi.6b", sym_name_ioff);
607 TRACE_SYMTAB(" ignore -- invalid OPD fn_descr offset: %s\n",
608 sym_name);
609 if (sym_name) ML_(dinfo_free)(sym_name);
612 return False;
615 /* This can't fail now, because we just checked the offset
616 above. */
617 ML_(img_get)(&fn_descr[0], escn_opd->img,
618 escn_opd->ioff + offset_in_opd, sizeof(fn_descr));
620 if (details)
621 TRACE_SYMTAB("opdXXY: offset %d, fn_descr %p\n",
622 offset_in_opd, fn_descr);
623 if (details)
624 TRACE_SYMTAB("opdXXZ: *fn_descr %p\n", (void*)(fn_descr[0]));
626 /* opd_bias is the what we have to add to SVMAs found in .opd to
627 get plausible .text AVMAs for the entry point, and .data
628 AVMAs (presumably) for the TOC locations. We use the caller
629 supplied value (which is di->text_bias) for both of these.
630 Not sure why that is correct - it seems to work, and sounds
631 OK for fn_descr[0], but surely we need to use the data bias
632 and not the text bias for fn_descr[1] ? Oh Well.
634 (*sym_avmas_out).main = fn_descr[0] + opd_bias;
635 SET_TOCPTR_AVMA(*sym_avmas_out, fn_descr[1] + opd_bias);
636 *from_opd_out = True;
637 is_in_opd = True;
639 /* Do a final sanity check: if the symbol falls outside the
640 DebugInfo's mapped range, ignore it. Since (*sym_avmas_out).main has
641 been updated, that can be achieved simply by falling through
642 to the test below. */
644 # endif /* ppc64-linux nasty hack */
647 /* Here's yet another ppc64-linux hack. Get rid of leading dot if
648 the symbol is outside .opd. */
649 # if defined(VGP_ppc64be_linux)
650 if (di->opd_size > 0
651 && !is_in_opd
652 && *sym_name_out_ioff != DiOffT_INVALID
653 && ML_(img_get_UChar)(escn_strtab->img, *sym_name_out_ioff) == '.') {
654 vg_assert(!(*from_opd_out));
655 (*sym_name_out_ioff)++;
657 # endif
659 /* If no part of the symbol falls within the mapped range,
660 ignore it. */
662 in_text
663 = di->text_present
664 && di->text_size > 0
665 && !((*sym_avmas_out).main + *sym_size_out <= di->text_avma
666 || (*sym_avmas_out).main >= di->text_avma + di->text_size);
668 in_data
669 = di->data_present
670 && di->data_size > 0
671 && !((*sym_avmas_out).main + *sym_size_out <= di->data_avma
672 || (*sym_avmas_out).main >= di->data_avma + di->data_size);
674 in_sdata
675 = di->sdata_present
676 && di->sdata_size > 0
677 && !((*sym_avmas_out).main + *sym_size_out <= di->sdata_avma
678 || (*sym_avmas_out).main >= di->sdata_avma + di->sdata_size);
680 in_rodata
681 = di->rodata_present
682 && di->rodata_size > 0
683 && !((*sym_avmas_out).main + *sym_size_out <= di->rodata_avma
684 || (*sym_avmas_out).main >= di->rodata_avma + di->rodata_size);
686 in_bss
687 = di->bss_present
688 && di->bss_size > 0
689 && !((*sym_avmas_out).main + *sym_size_out <= di->bss_avma
690 || (*sym_avmas_out).main >= di->bss_avma + di->bss_size);
692 in_sbss
693 = di->sbss_present
694 && di->sbss_size > 0
695 && !((*sym_avmas_out).main + *sym_size_out <= di->sbss_avma
696 || (*sym_avmas_out).main >= di->sbss_avma + di->sbss_size);
699 if (*is_text_out) {
700 /* This used to reject any symbol falling outside the text
701 segment ("if (!in_text) ..."). Now it is relaxed slightly,
702 to reject only symbols which fall outside the area mapped
703 r-x. This is in accordance with r7427. See
704 "Comment_Regarding_Text_Range_Checks" in storage.c for
705 background. */
706 Bool in_rx;
707 vg_assert(di->fsm.have_rx_map);
708 /* This could actually wrap around and cause
709 ML_(find_rx_mapping) to assert. But that seems so unlikely,
710 let's wait for it to happen before fixing it. */
711 in_rx = (ML_(find_rx_mapping)(
713 (*sym_avmas_out).main,
714 (*sym_avmas_out).main + *sym_size_out - 1) != NULL);
715 if (in_text)
716 vg_assert(in_rx);
717 if (!in_rx) {
718 TRACE_SYMTAB(
719 "ignore -- %#lx .. %#lx outside .text svma range %#lx .. %#lx\n",
720 (*sym_avmas_out).main, (*sym_avmas_out).main + *sym_size_out - 1,
721 di->text_avma,
722 di->text_avma + di->text_size - 1);
723 return False;
725 } else {
726 if (!(in_data || in_sdata || in_rodata || in_bss || in_sbss)) {
727 TRACE_SYMTAB(
728 "ignore -- %#lx .. %#lx outside .data / .sdata / .rodata "
729 "/ .bss / .sbss svma ranges\n",
730 (*sym_avmas_out).main, (*sym_avmas_out).main + *sym_size_out - 1);
731 return False;
735 # if defined(VGP_ppc64be_linux)
736 if (di->opd_present && di->opd_size > 0) {
737 vg_assert((*sym_avmas_out).main + *sym_size_out <= di->opd_avma
738 || (*sym_avmas_out).main >= di->opd_avma + di->opd_size);
740 #endif
742 # if defined(VGP_ppc64le_linux)
743 /* PPC64 LE ABI uses three bits in the st_other field to indicate the number
744 * of instructions between the function's global and local entry points. An
745 * offset of 0 indicates that there is one entry point. The value must be:
747 * 0 - one entry point, local and global are the same
748 * 1 - reserved
749 * 2 - local entry point is one instruction after the global entry point
750 * 3 - local entry point is two instructions after the global entry point
751 * 4 - local entry point is four instructions after the global entry point
752 * 5 - local entry point is eight instructions after the global entry point
753 * 6 - local entry point is sixteen instructions after the global entry point
754 * 7 - reserved
756 * Extract the three bit field from the other field is done by:
757 * (other_field & STO_PPC64_LOCAL_MASK) >> STO_PPC_LOCAL_BIT
759 * where the #define values are given in include/elf/powerpc.h file for
760 * the PPC binutils.
762 * conversion of the three bit field to bytes is given by
764 * ((1 << bit_field) >> 2) << 2
767 #define STO_PPC64_LOCAL_BIT 5
768 #define STO_PPC64_LOCAL_MASK (7 << STO_PPC64_LOCAL_BIT)
770 unsigned int bit_field, dist_to_local_entry;
771 /* extract the other filed */
772 bit_field = (sym->st_other & STO_PPC64_LOCAL_MASK) >> STO_PPC64_LOCAL_BIT;
774 if ((bit_field > 0) && (bit_field < 7)) {
775 /* store the local entry point address */
776 dist_to_local_entry = ((1 << bit_field) >> 2) << 2;
777 SET_LOCAL_EP_AVMA(*sym_avmas_out,
778 (*sym_avmas_out).main + dist_to_local_entry);
780 if (TRACE_SYMTAB_ENABLED) {
781 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
782 "di.gesi.5", sym_name_ioff);
783 VG_(printf)("Local entry point: %s at %#010x\n",
784 sym_name,
785 (unsigned int)GET_LOCAL_EP_AVMA(*sym_avmas_out));
789 # endif
791 /* Acquire! */
792 return True;
796 /* Read an ELF symbol table (normal or dynamic). This one is for the
797 "normal" case ({x86,amd64,ppc32,arm,mips32,mips64, ppc64le}-linux). */
798 static
799 __attribute__((unused)) /* not referred to on all targets */
800 void read_elf_symtab__normal(
801 struct _DebugInfo* di, const HChar* tab_name,
802 DiSlice* escn_symtab,
803 DiSlice* escn_strtab,
804 DiSlice* escn_opd, /* ppc64be-linux only */
805 Bool symtab_in_debug
808 if (escn_strtab->img == NULL || escn_symtab->img == NULL) {
809 HChar buf[VG_(strlen)(tab_name) + 40];
810 VG_(sprintf)(buf, " object doesn't have a %s", tab_name);
811 ML_(symerr)(di, False, buf);
812 return;
815 TRACE_SYMTAB("\n--- Reading (ELF, standard) %s (%llu entries) ---\n",
816 tab_name, escn_symtab->szB/sizeof(ElfXX_Sym) );
818 /* Perhaps should start at i = 1; ELF docs suggest that entry
819 0 always denotes 'unknown symbol'. */
820 Word i;
821 for (i = 1; i < (Word)(escn_symtab->szB/sizeof(ElfXX_Sym)); i++) {
822 ElfXX_Sym sym;
823 ML_(img_get)(&sym, escn_symtab->img,
824 escn_symtab->ioff + i * sizeof(ElfXX_Sym), sizeof(sym));
825 DiOffT sym_name = escn_strtab->ioff + sym.st_name;
826 Addr sym_svma = sym.st_value;
828 if (di->trace_symtab)
829 show_raw_elf_symbol(escn_strtab->img, i,
830 &sym, sym_name, sym_svma, False);
832 SymAVMAs sym_avmas_really;
833 Int sym_size = 0;
834 Bool from_opd = False, is_text = False, is_ifunc = False;
835 Bool is_global = False;
836 DiOffT sym_name_really = DiOffT_INVALID;
837 sym_avmas_really.main = 0;
838 SET_TOCPTR_AVMA(sym_avmas_really, 0);
839 SET_LOCAL_EP_AVMA(sym_avmas_really, 0);
840 if (get_elf_symbol_info(di, &sym, sym_name, escn_strtab,
841 sym_svma, symtab_in_debug,
842 escn_opd, di->text_bias,
843 &sym_name_really,
844 &sym_avmas_really,
845 &sym_size,
846 &from_opd, &is_text, &is_ifunc, &is_global)) {
848 DiSym disym;
849 VG_(memset)(&disym, 0, sizeof(disym));
850 HChar* cstr = ML_(img_strdup)(escn_strtab->img,
851 "di.res__n.1", sym_name_really);
852 disym.avmas = sym_avmas_really;
853 disym.pri_name = ML_(addStr) ( di, cstr, -1 );
854 disym.sec_names = NULL;
855 disym.size = sym_size;
856 disym.isText = is_text;
857 disym.isIFunc = is_ifunc;
858 disym.isGlobal = is_global;
859 if (cstr) { ML_(dinfo_free)(cstr); cstr = NULL; }
860 vg_assert(disym.pri_name);
861 vg_assert(GET_TOCPTR_AVMA(disym.avmas) == 0);
862 /* has no role except on ppc64be-linux */
863 ML_(addSym) ( di, &disym );
865 if (TRACE_SYMTAB_ENABLED) {
866 TRACE_SYMTAB(" rec(%c) [%4ld]: "
867 " val %#010lx, sz %4d %s\n",
868 is_text ? 't' : 'd',
870 disym.avmas.main,
871 (Int)disym.size,
872 disym.pri_name
874 if (GET_LOCAL_EP_AVMA(disym.avmas) != 0) {
875 TRACE_SYMTAB(" local entry point %#010lx\n",
876 GET_LOCAL_EP_AVMA(disym.avmas));
885 /* Read an ELF symbol table (normal or dynamic). This one is for
886 ppc64be-linux, which requires special treatment. */
888 typedef
889 struct {
890 Addr addr;
891 DiOffT name;
892 /* We have to store also the DiImage* so as to give context for
893 |name|. This is not part of the key (in terms of lookup) but
894 there's no easy other way to do this. Ugly. */
895 DiImage* img;
897 TempSymKey;
899 typedef
900 struct {
901 TempSymKey key;
902 Addr tocptr;
903 Int size;
904 Bool from_opd;
905 Bool is_text;
906 Bool is_ifunc;
907 Bool is_global;
909 TempSym;
911 static Word cmp_TempSymKey ( const TempSymKey* key1, const TempSym* elem2 )
913 /* Stay sane ... */
914 vg_assert(key1->img == elem2->key.img);
915 vg_assert(key1->img != NULL);
916 if (key1->addr < elem2->key.addr) return -1;
917 if (key1->addr > elem2->key.addr) return 1;
918 vg_assert(key1->name != DiOffT_INVALID);
919 vg_assert(elem2->key.name != DiOffT_INVALID);
920 return (Word)ML_(img_strcmp)(key1->img, key1->name, elem2->key.name);
923 static
924 __attribute__((unused)) /* not referred to on all targets */
925 void read_elf_symtab__ppc64be_linux(
926 struct _DebugInfo* di, const HChar* tab_name,
927 DiSlice* escn_symtab,
928 DiSlice* escn_strtab,
929 DiSlice* escn_opd, /* ppc64be-linux only */
930 Bool symtab_in_debug
933 Word i;
934 Int old_size;
935 Bool modify_size, modify_tocptr;
936 OSet *oset;
937 TempSymKey key;
938 TempSym *elem;
939 TempSym *prev;
941 if (escn_strtab->img == NULL || escn_symtab->img == NULL) {
942 HChar buf[VG_(strlen)(tab_name) + 40];
943 VG_(sprintf)(buf, " object doesn't have a %s", tab_name);
944 ML_(symerr)(di, False, buf);
945 return;
948 TRACE_SYMTAB("\n--- Reading (ELF, ppc64be-linux) %s (%llu entries) ---\n",
949 tab_name, escn_symtab->szB/sizeof(ElfXX_Sym) );
951 oset = VG_(OSetGen_Create)( offsetof(TempSym,key),
952 (OSetCmp_t)cmp_TempSymKey,
953 ML_(dinfo_zalloc), "di.respl.1",
954 ML_(dinfo_free) );
956 /* Perhaps should start at i = 1; ELF docs suggest that entry
957 0 always denotes 'unknown symbol'. */
958 for (i = 1; i < (Word)(escn_symtab->szB/sizeof(ElfXX_Sym)); i++) {
959 ElfXX_Sym sym;
960 ML_(img_get)(&sym, escn_symtab->img,
961 escn_symtab->ioff + i * sizeof(ElfXX_Sym), sizeof(sym));
962 DiOffT sym_name = escn_strtab->ioff + sym.st_name;
963 Addr sym_svma = sym.st_value;
965 if (di->trace_symtab)
966 show_raw_elf_symbol(escn_strtab->img, i,
967 &sym, sym_name, sym_svma, True);
969 SymAVMAs sym_avmas_really;
970 Int sym_size = 0;
971 Bool from_opd = False, is_text = False, is_ifunc = False;
972 Bool is_global = False;
973 DiOffT sym_name_really = DiOffT_INVALID;
974 DiSym disym;
975 VG_(memset)(&disym, 0, sizeof(disym));
976 sym_avmas_really.main = 0;
977 SET_TOCPTR_AVMA(sym_avmas_really, 0);
978 SET_LOCAL_EP_AVMA(sym_avmas_really, 0);
979 if (get_elf_symbol_info(di, &sym, sym_name, escn_strtab,
980 sym_svma, symtab_in_debug,
981 escn_opd, di->text_bias,
982 &sym_name_really,
983 &sym_avmas_really,
984 &sym_size,
985 &from_opd, &is_text, &is_ifunc, &is_global)) {
987 /* Check if we've seen this (name,addr) key before. */
988 key.addr = sym_avmas_really.main;
989 key.name = sym_name_really;
990 key.img = escn_strtab->img;
991 prev = VG_(OSetGen_Lookup)( oset, &key );
993 if (prev) {
995 /* Seen it before. Fold in whatever new info we can. */
996 modify_size = False;
997 modify_tocptr = False;
998 old_size = 0;
1000 if (prev->from_opd && !from_opd
1001 && (prev->size == 24 || prev->size == 16)
1002 && sym_size != prev->size) {
1003 /* Existing one is an opd-redirect, with a bogus size,
1004 so the only useful new fact we have is the real size
1005 of the symbol. */
1006 modify_size = True;
1007 old_size = prev->size;
1008 prev->size = sym_size;
1010 else
1011 if (!prev->from_opd && from_opd
1012 && (sym_size == 24 || sym_size == 16)) {
1013 /* Existing one is non-opd, new one is opd. What we
1014 can acquire from the new one is the TOC ptr to be
1015 used. Since the existing sym is non-toc, it
1016 shouldn't currently have an known TOC ptr. */
1017 vg_assert(prev->tocptr == 0);
1018 modify_tocptr = True;
1019 prev->tocptr = GET_TOCPTR_AVMA(sym_avmas_really);
1021 else {
1022 /* ignore. can we do better here? */
1025 /* Only one or the other is possible (I think) */
1026 vg_assert(!(modify_size && modify_tocptr));
1028 if (modify_size && di->trace_symtab) {
1029 VG_(printf)(" modify (old sz %4d) "
1030 " val %#010lx, toc %#010lx, sz %4d %llu\n",
1031 old_size,
1032 prev->key.addr,
1033 prev->tocptr,
1034 prev->size,
1035 prev->key.name
1038 if (modify_tocptr && di->trace_symtab) {
1039 VG_(printf)(" modify (upd tocptr) "
1040 " val %#010lx, toc %#010lx, sz %4d %llu\n",
1041 prev->key.addr,
1042 prev->tocptr,
1043 prev->size,
1044 prev->key.name
1048 } else {
1050 /* A new (name,addr) key. Add and continue. */
1051 elem = VG_(OSetGen_AllocNode)(oset, sizeof(TempSym));
1052 elem->key = key;
1053 elem->tocptr = GET_TOCPTR_AVMA(sym_avmas_really);
1054 elem->size = sym_size;
1055 elem->from_opd = from_opd;
1056 elem->is_text = is_text;
1057 elem->is_ifunc = is_ifunc;
1058 elem->is_global = is_global;
1059 VG_(OSetGen_Insert)(oset, elem);
1060 if (di->trace_symtab) {
1061 HChar* str = ML_(img_strdup)(escn_strtab->img, "di.respl.2",
1062 elem->key.name);
1063 VG_(printf)(" to-oset [%4ld]: "
1064 " val %#010lx, toc %#010lx, sz %4d %s\n",
1066 elem->key.addr,
1067 elem->tocptr,
1068 (Int) elem->size,
1071 if (str) ML_(dinfo_free)(str);
1078 /* All the syms that matter are in the oset. Now pull them out,
1079 build a "standard" symbol table, and nuke the oset. */
1081 i = 0;
1082 VG_(OSetGen_ResetIter)( oset );
1084 while ( (elem = VG_(OSetGen_Next)(oset)) ) {
1085 DiSym disym;
1086 VG_(memset)(&disym, 0, sizeof(disym));
1087 HChar* cstr = ML_(img_strdup)(escn_strtab->img,
1088 "di.res__ppc64.1", elem->key.name);
1089 disym.avmas.main = elem->key.addr;
1090 SET_TOCPTR_AVMA(disym.avmas, elem->tocptr);
1091 SET_LOCAL_EP_AVMA(disym.avmas, 0); // ppc64be does not use local_ep.
1092 disym.pri_name = ML_(addStr) ( di, cstr, -1 );
1093 disym.sec_names = NULL;
1094 disym.size = elem->size;
1095 disym.isText = elem->is_text;
1096 disym.isIFunc = elem->is_ifunc;
1097 disym.isGlobal = elem->is_global;
1098 if (cstr) { ML_(dinfo_free)(cstr); cstr = NULL; }
1099 vg_assert(disym.pri_name != NULL);
1101 ML_(addSym) ( di, &disym );
1102 if (di->trace_symtab) {
1103 VG_(printf)(" rec(%c%c%c) [%4ld]: "
1104 " val %#010lx, toc %#010lx, sz %4d %s\n",
1105 disym.isText ? 't' : 'd',
1106 disym.isIFunc ? 'i' : '-',
1107 disym.isGlobal ? 'g' : 'l',
1109 disym.avmas.main,
1110 GET_TOCPTR_AVMA(disym.avmas),
1111 (Int) disym.size,
1112 disym.pri_name
1115 i++;
1118 VG_(OSetGen_Destroy)( oset );
1123 * Look for a build-id in an ELF image. The build-id specification
1124 * can be found here:
1126 * http://fedoraproject.org/wiki/RolandMcGrath/BuildID
1128 * Returned string must be freed by the caller.
1130 static
1131 HChar* find_buildid(DiImage* img, Bool rel_ok, Bool search_shdrs)
1133 HChar* buildid = NULL;
1135 # ifdef NT_GNU_BUILD_ID
1136 if (is_elf_object_file_by_DiImage(img, rel_ok)) {
1137 Word i;
1139 ElfXX_Ehdr ehdr;
1140 ML_(img_get)(&ehdr, img, 0, sizeof(ehdr));
1141 /* Skip the phdrs when we have to search the shdrs. In separate
1142 .debug files the phdrs might not be valid (they are a copy of
1143 the main ELF file) and might trigger assertions when getting
1144 image notes based on them. */
1145 for (i = 0; !search_shdrs && i < ehdr.e_phnum; i++) {
1146 ElfXX_Phdr phdr;
1147 ML_(img_get)(&phdr, img,
1148 ehdr.e_phoff + i * ehdr.e_phentsize, sizeof(phdr));
1150 if (phdr.p_type == PT_NOTE) {
1151 ElfXX_Off note_ioff = phdr.p_offset;
1153 while (note_ioff < phdr.p_offset + phdr.p_filesz) {
1154 ElfXX_Nhdr note;
1155 ML_(img_get)(&note, img, (DiOffT)note_ioff, sizeof(note));
1156 DiOffT name_ioff = note_ioff + sizeof(ElfXX_Nhdr);
1157 DiOffT desc_ioff = name_ioff + ((note.n_namesz + 3) & ~3);
1158 if (ML_(img_strcmp_c)(img, name_ioff, ELF_NOTE_GNU) == 0
1159 && note.n_type == NT_GNU_BUILD_ID) {
1160 buildid = ML_(dinfo_zalloc)("di.fbi.1",
1161 note.n_descsz * 2 + 1);
1162 Word j;
1163 for (j = 0; j < note.n_descsz; j++) {
1164 UChar desc_j = ML_(img_get_UChar)(img, desc_ioff + j);
1165 VG_(sprintf)(buildid + VG_(strlen)(buildid),
1166 "%02x", (UInt)desc_j);
1170 note_ioff = note_ioff + sizeof(ElfXX_Nhdr)
1171 + ((note.n_namesz + 3) & ~3)
1172 + ((note.n_descsz + 3) & ~3);
1177 /* Normally we would only search shdrs for ET_REL files, but when
1178 we search for a separate .debug file phdrs might not be there
1179 (they are never loaded) or have been corrupted, so try again
1180 against shdrs. */
1181 if (buildid || (!rel_ok && !search_shdrs))
1182 return buildid;
1184 for (i = 0; i < ehdr.e_shnum; i++) {
1185 ElfXX_Shdr shdr;
1186 ML_(img_get)(&shdr, img,
1187 ehdr.e_shoff + i * ehdr.e_shentsize, sizeof(shdr));
1189 if (shdr.sh_type == SHT_NOTE) {
1190 ElfXX_Off note_ioff = shdr.sh_offset;
1192 while (note_ioff < shdr.sh_offset + shdr.sh_size) {
1193 ElfXX_Nhdr note;
1194 ML_(img_get)(&note, img, (DiOffT)note_ioff, sizeof(note));
1195 DiOffT name_ioff = note_ioff + sizeof(ElfXX_Nhdr);
1196 DiOffT desc_ioff = name_ioff + ((note.n_namesz + 3) & ~3);
1198 if (ML_(img_strcmp_c)(img, name_ioff, ELF_NOTE_GNU) == 0
1199 && note.n_type == NT_GNU_BUILD_ID) {
1200 buildid = ML_(dinfo_zalloc)("di.fbi.2",
1201 note.n_descsz * 2 + 1);
1202 Word j;
1203 for (j = 0; j < note.n_descsz; j++) {
1204 UChar desc_j = ML_(img_get_UChar)(img, desc_ioff + j);
1205 VG_(sprintf)(buildid + VG_(strlen)(buildid),
1206 "%02x", (UInt)desc_j);
1210 note_ioff = note_ioff + sizeof(ElfXX_Nhdr)
1211 + ((note.n_namesz + 3) & ~3)
1212 + ((note.n_descsz + 3) & ~3);
1217 # endif /* def NT_GNU_BUILD_ID */
1219 return buildid;
1223 /* Try and open a separate debug file, ignoring any where the CRC does
1224 not match the value from the main object file. Returned DiImage
1225 must be discarded by the caller.
1227 If |serverAddr| is NULL, |name| is expected to be a fully qualified
1228 (absolute) path to the file in the local filesystem. If
1229 |serverAddr| is non-NULL, it is expected to be an IPv4 and port
1230 spec of the form "d.d.d.d:d" or "d.d.d.d", and |name| is expected
1231 to be a plain filename (no path components at all).
1233 static
1234 DiImage* open_debug_file( const HChar* name, const HChar* buildid, UInt crc,
1235 Bool rel_ok, const HChar* serverAddr )
1237 DiImage* dimg
1238 = serverAddr ? ML_(img_from_di_server)(name, serverAddr)
1239 : ML_(img_from_local_file)(name);
1240 if (dimg == NULL)
1241 return NULL;
1243 if (VG_(clo_verbosity) > 1) {
1244 if (serverAddr)
1245 VG_(message)(Vg_DebugMsg, " Considering %s on server %s ..\n",
1246 name, serverAddr);
1247 else
1248 VG_(message)(Vg_DebugMsg, " Considering %s ..\n", name);
1251 /* We will always check the crc if we have one (altfiles don't have one)
1252 for now because we might be opening the main file again by any other
1253 name, and that obviously also has the same buildid. More efficient
1254 would be an fstat bases check or a check that the file actually
1255 contains .debug* sections. */
1256 if (buildid && crc == 0) {
1257 HChar* debug_buildid = find_buildid(dimg, rel_ok, True);
1258 if (debug_buildid == NULL || VG_(strcmp)(buildid, debug_buildid) != 0) {
1259 ML_(img_done)(dimg);
1260 if (VG_(clo_verbosity) > 1)
1261 VG_(message)(Vg_DebugMsg,
1262 " .. build-id mismatch (found %s wanted %s)\n",
1263 debug_buildid, buildid);
1264 ML_(dinfo_free)(debug_buildid);
1265 return NULL;
1267 ML_(dinfo_free)(debug_buildid);
1268 if (VG_(clo_verbosity) > 1)
1269 VG_(message)(Vg_DebugMsg, " .. build-id is valid\n");
1270 } else {
1271 UInt calccrc = ML_(img_calc_gnu_debuglink_crc32)(dimg);
1272 if (calccrc != crc) {
1273 ML_(img_done)(dimg);
1274 if (VG_(clo_verbosity) > 1)
1275 VG_(message)(Vg_DebugMsg,
1276 " .. CRC mismatch (computed %08x wanted %08x)\n", calccrc, crc);
1277 return NULL;
1280 if (VG_(clo_verbosity) > 1)
1281 VG_(message)(Vg_DebugMsg, " .. CRC is valid\n");
1284 return dimg;
1287 #if defined(VGO_linux)
1288 /* Return the path of the debuginfod-find executable. */
1289 static
1290 const HChar* debuginfod_find_path( void )
1292 static const HChar* path = (const HChar*) -1;
1294 if (path == (const HChar*) -1) {
1295 if (VG_(getenv)("DEBUGINFOD_URLS") == NULL
1296 || VG_(strcmp)("", VG_(getenv("DEBUGINFOD_URLS"))) == 0)
1297 path = NULL;
1298 else
1299 path = VG_(find_executable)("debuginfod-find");
1302 return path;
1305 /* Try to find a separate debug file with |buildid| via debuginfod. If found,
1306 return its DiImage. Searches for a local debuginfod-find executable and
1307 runs it in a child process in order to download the debug file. */
1308 static
1309 DiImage* find_debug_file_debuginfod( const HChar* objpath,
1310 HChar** debugpath,
1311 const HChar* buildid,
1312 const UInt crc, Bool rel_ok )
1314 # define BUF_SIZE 4096
1315 Int out_fds[2], err_fds[2]; /* pipe fds */
1316 DiImage* dimg = NULL; /* the img we found */
1317 HChar buf[BUF_SIZE]; /* executable output buffer */
1318 const HChar* path; /* executable path */
1319 SizeT len; /* number of bytes read int buf */
1320 Int ret; /* result of read call */
1322 if (buildid == NULL)
1323 return NULL;
1325 if ((path = debuginfod_find_path()) == NULL)
1326 return NULL;
1328 if (VG_(pipe)(out_fds) != 0
1329 || VG_(pipe)(err_fds) != 0)
1330 return NULL;
1332 if (VG_(clo_verbosity) > 1)
1333 VG_(umsg)("Downloading debug info for %s...\n", objpath);
1335 /* Run debuginfod-find to query servers for the debuginfo. */
1336 Int pid = VG_(fork)();
1337 if (pid == 0) {
1338 const HChar *argv[4] = { path, "debuginfo", buildid, (HChar*)0 };
1340 /* Redirect stdout and stderr */
1341 SysRes res = VG_(dup2)(out_fds[1], 1);
1342 if (sr_Res(res) < 0)
1343 VG_(exit)(1);
1345 res = VG_(dup2)(err_fds[1], 2);
1346 if (sr_Res(res) < 0)
1347 VG_(exit)(1);
1349 /* Disable extra stderr output since it does not play well with umesg */
1350 VG_(env_unsetenv)(VG_(client_envp), "DEBUGINFOD_VERBOSE", NULL);
1351 VG_(env_unsetenv)(VG_(client_envp), "DEBUGINFOD_PROGRESS", NULL);
1353 VG_(close)(out_fds[0]);
1354 VG_(close)(err_fds[0]);
1355 VG_(execv)(argv[0], argv);
1357 /* If we are still alive here, execv failed. */
1358 VG_(exit)(1);
1361 VG_(close)(out_fds[1]);
1362 VG_(close)(err_fds[1]);
1364 if (pid < 0) {
1365 if (VG_(clo_verbosity) > 1)
1366 VG_(umsg)("Server Error\n");
1367 goto out;
1369 VG_(waitpid)(pid, NULL, 0);
1371 /* Set dimg if download was successful. */
1372 len = 0;
1373 ret = -1;
1374 while (len >= 0 && len < BUF_SIZE) {
1375 ret = VG_(read)(out_fds[0], buf + len, BUF_SIZE - len);
1376 if (ret <= 0)
1377 break;
1378 len += ret;
1380 if (ret >= 0 && len > 0
1381 && buf[0] == '/' && buf[len-1] == '\n') {
1383 /* Remove newline from filename before trying to open debug file */
1384 buf[len-1] = '\0';
1385 dimg = open_debug_file(buf, buildid, crc, rel_ok, NULL);
1386 if (dimg != NULL) {
1387 /* Success */
1388 if (*debugpath)
1389 ML_(dinfo_free)(*debugpath);
1391 *debugpath = ML_(dinfo_strdup)("di.fdfd.1", buf);
1392 if (VG_(clo_verbosity) > 1)
1393 VG_(umsg)("Successfully downloaded debug file for %s\n",
1394 objpath);
1395 goto out;
1399 /* Download failed so try to print error message. */
1400 HChar* nl;
1401 if (VG_(read)(err_fds[0], buf, BUF_SIZE) > 0
1402 && (nl = VG_(strchr)(buf, '\n'))) {
1403 *nl = '\0';
1404 if (VG_(clo_verbosity) > 1)
1405 VG_(umsg)("%s\n", buf);
1406 } else
1407 if (VG_(clo_verbosity) > 1)
1408 VG_(umsg)("Server Error\n");
1410 out:
1411 VG_(close)(out_fds[0]);
1412 VG_(close)(err_fds[0]);
1413 return dimg;
1415 #endif
1417 /* Try to find a separate debug file for a given object file. If
1418 found, return its DiImage, which should be freed by the caller. If
1419 |buildid| is non-NULL, then a debug object matching it is
1420 acceptable. If |buildid| is NULL or doesn't specify a findable
1421 debug object, then we look in various places to find a file with
1422 the specified CRC. And if that doesn't work out then we give
1423 up. */
1424 static
1425 DiImage* find_debug_file( struct _DebugInfo* di,
1426 const HChar* objpath, const HChar* buildid,
1427 const HChar* debugname, UInt crc, Bool rel_ok )
1429 const HChar* extrapath = VG_(clo_extra_debuginfo_path);
1430 const HChar* serverpath = VG_(clo_debuginfo_server);
1432 DiImage* dimg = NULL; /* the img that we found */
1433 HChar* debugpath = NULL; /* where we found it */
1435 if (buildid != NULL) {
1436 debugpath = ML_(dinfo_zalloc)("di.fdf.1",
1437 VG_(strlen)(buildid) + 33);
1439 VG_(sprintf)(debugpath, "/usr/lib/debug/.build-id/%c%c/%s.debug",
1440 buildid[0], buildid[1], buildid + 2);
1442 dimg = open_debug_file(debugpath, buildid, 0, rel_ok, NULL);
1443 if (!dimg) {
1444 ML_(dinfo_free)(debugpath);
1445 debugpath = NULL;
1449 if (dimg == NULL && debugname != NULL) {
1450 HChar *objdir = ML_(dinfo_strdup)("di.fdf.2", objpath);
1451 HChar *usrmerge_objdir;
1452 HChar *objdirptr;
1454 if ((objdirptr = VG_(strrchr)(objdir, '/')) != NULL)
1455 *objdirptr = '\0';
1457 if ((objdirptr = VG_(strstr)(objdir, "usr")) != NULL)
1458 usrmerge_objdir = objdirptr + VG_(strlen)("usr");
1459 else
1460 usrmerge_objdir = NULL;
1462 debugpath = ML_(dinfo_zalloc)(
1463 "di.fdf.3",
1464 VG_(strlen)(objdir) + VG_(strlen)(debugname) + 64
1465 + (extrapath ? VG_(strlen)(extrapath) : 0)
1466 + (serverpath ? VG_(strlen)(serverpath) : 0));
1468 # define TRY_OBJDIR(format, ...) \
1469 do { \
1470 VG_(sprintf)(debugpath, format, __VA_ARGS__); \
1471 dimg = open_debug_file(debugpath, buildid, crc, rel_ok, NULL); \
1472 if (dimg != NULL) goto dimg_ok; \
1473 } while (0);
1475 # define TRY_OBJDIR_USRMERGE_OBJDIR(format) \
1476 do { \
1477 TRY_OBJDIR(format, objdir, debugname); \
1478 if (usrmerge_objdir != NULL) { \
1479 TRY_OBJDIR(format, usrmerge_objdir, debugname); \
1481 } while (0)
1483 if (debugname[0] == '/') {
1484 TRY_OBJDIR("%s", debugname);
1487 TRY_OBJDIR_USRMERGE_OBJDIR("%s/%s");
1488 TRY_OBJDIR_USRMERGE_OBJDIR("%s/.debug/%s");
1489 TRY_OBJDIR_USRMERGE_OBJDIR("/usr/lib/debug%s/%s");
1491 if (extrapath) {
1492 TRY_OBJDIR("%s%s/%s", extrapath, objdir, debugname);
1493 if (usrmerge_objdir != NULL)
1494 TRY_OBJDIR("%s%s/%s", extrapath, usrmerge_objdir, debugname);
1496 # undef TRY_OBJDIR
1497 # undef TRY_OBJDIRS
1499 if (serverpath) {
1500 /* When looking on the debuginfo server, always just pass the
1501 basename. */
1502 const HChar* basename = debugname;
1503 if (VG_(strstr)(basename, "/") != NULL) {
1504 basename = VG_(strrchr)(basename, '/') + 1;
1506 VG_(sprintf)(debugpath, "%s on %s", basename, serverpath);
1507 dimg = open_debug_file(basename, buildid, crc, rel_ok, serverpath);
1508 if (dimg) goto dimg_ok;
1511 dimg_ok:
1513 ML_(dinfo_free)(objdir);
1516 # if defined(VGO_linux)
1517 if (dimg == NULL)
1518 dimg = find_debug_file_debuginfod(objpath, &debugpath, buildid, crc, rel_ok);
1519 # endif
1521 if (dimg != NULL) {
1522 vg_assert(debugpath);
1523 TRACE_SYMTAB("\n");
1524 TRACE_SYMTAB("------ Found a debuginfo file: %s\n", debugpath);
1526 /* Only set once, we might be called again for opening the altfile. */
1527 if (di->fsm.dbgname == NULL)
1528 di->fsm.dbgname = ML_(dinfo_strdup)("di.fdf.4", debugpath);
1531 if (debugpath)
1532 ML_(dinfo_free)(debugpath);
1534 return dimg;
1538 /* Try to find a separate debug file for a given object file, in a
1539 hacky and dangerous way: check only the --extra-debuginfo-path and
1540 the --debuginfo-server. And don't do a consistency check. */
1541 static
1542 DiImage* find_debug_file_ad_hoc( const DebugInfo* di,
1543 const HChar* objpath )
1545 const HChar* extrapath = VG_(clo_extra_debuginfo_path);
1546 const HChar* serverpath = VG_(clo_debuginfo_server);
1548 DiImage* dimg = NULL; /* the img that we found */
1549 HChar* debugpath = NULL; /* where we found it */
1551 HChar *objdir = ML_(dinfo_strdup)("di.fdfah.1", objpath);
1552 HChar *objdirptr;
1554 if ((objdirptr = VG_(strrchr)(objdir, '/')) != NULL)
1555 *objdirptr = '\0';
1557 debugpath = ML_(dinfo_zalloc)(
1558 "di.fdfah.3",
1559 VG_(strlen)(objdir) + 64
1560 + (extrapath ? VG_(strlen)(extrapath) : 0)
1561 + (serverpath ? VG_(strlen)(serverpath) : 0));
1563 if (extrapath) {
1564 VG_(sprintf)(debugpath, "%s/%s", extrapath, objpath);
1565 dimg = ML_(img_from_local_file)(debugpath);
1566 if (dimg != NULL) {
1567 if (VG_(clo_verbosity) > 1) {
1568 VG_(message)(Vg_DebugMsg, " Using (POSSIBLY MISMATCHED) %s\n",
1569 debugpath);
1571 goto dimg_ok;
1574 if (serverpath) {
1575 /* When looking on the debuginfo server, always just pass the
1576 basename. */
1577 const HChar* basename = objpath;
1578 if (VG_(strstr)(basename, "/") != NULL) {
1579 basename = VG_(strrchr)(basename, '/') + 1;
1581 VG_(sprintf)(debugpath, "%s on %s", basename, serverpath);
1582 dimg = ML_(img_from_di_server)(basename, serverpath);
1583 if (dimg != NULL) {
1584 if (VG_(clo_verbosity) > 1) {
1585 VG_(message)(Vg_DebugMsg, " Using (POSSIBLY MISMATCHED) %s\n",
1586 debugpath);
1588 goto dimg_ok;
1592 dimg_ok:
1594 ML_(dinfo_free)(objdir);
1596 if (dimg != NULL) {
1597 vg_assert(debugpath);
1598 TRACE_SYMTAB("\n");
1599 TRACE_SYMTAB("------ Found an ad_hoc debuginfo file: %s\n", debugpath);
1602 if (debugpath)
1603 ML_(dinfo_free)(debugpath);
1605 return dimg;
1609 static DiOffT INDEX_BIS ( DiOffT base, UWord idx, UWord scale ) {
1610 // This is a bit stupid. Really, idx and scale ought to be
1611 // 64-bit quantities, always.
1612 return base + (DiOffT)idx * (DiOffT)scale;
1616 /* Find the file offset corresponding to SVMA by using the program
1617 headers. This is taken from binutils-2.17/binutils/readelf.c
1618 offset_from_vma(). */
1619 static
1620 Word file_offset_from_svma ( /*OUT*/Bool* ok,
1621 Addr svma,
1622 DiImage* img,
1623 DiOffT phdr_ioff,
1624 Word phdr_nent,
1625 Word phdr_ent_szB )
1627 Word i;
1628 for (i = 0; i < phdr_nent; i++) {
1629 ElfXX_Phdr seg;
1630 ML_(img_get)(&seg, img,
1631 INDEX_BIS(phdr_ioff, i, phdr_ent_szB), sizeof(seg));
1632 if (seg.p_type != PT_LOAD)
1633 continue;
1634 if (svma >= (seg.p_vaddr & -seg.p_align)
1635 && svma + 1 <= seg.p_vaddr + seg.p_filesz) {
1636 *ok = True;
1637 return svma - seg.p_vaddr + seg.p_offset;
1640 *ok = False;
1641 return 0;
1644 /* Check if section is compressed and modify DiSlice if it is.
1645 Returns False in case of unsupported compression type.
1647 static Bool check_compression(ElfXX_Shdr* h, DiSlice* s) {
1648 if (h->sh_flags & SHF_COMPRESSED) {
1649 ElfXX_Chdr chdr;
1650 ML_(img_get)(&chdr, s->img, s->ioff, sizeof(ElfXX_Chdr));
1651 if (chdr.ch_type != ELFCOMPRESS_ZLIB)
1652 return False;
1653 s->ioff = ML_(img_mark_compressed_part)(s->img,
1654 s->ioff + sizeof(ElfXX_Chdr),
1655 s->szB - sizeof(ElfXX_Chdr),
1656 (SizeT)chdr.ch_size);
1657 s->szB = chdr.ch_size;
1658 } else if (h->sh_size > SIZE_OF_ZLIB_HEADER) {
1659 /* Read the zlib header. In this case, it should be "ZLIB"
1660 followed by the uncompressed section size, 8 bytes in BE order. */
1661 UChar tmp[SIZE_OF_ZLIB_HEADER];
1662 ML_(img_get)(tmp, s->img, s->ioff, SIZE_OF_ZLIB_HEADER);
1663 if (VG_(memcmp)(tmp, "ZLIB", 4) == 0) {
1664 SizeT size;
1665 # if (VG_WORDSIZE == 8)
1666 size = tmp[4]; size <<= 8;
1667 size += tmp[5]; size <<= 8;
1668 size += tmp[6]; size <<= 8;
1669 size += tmp[7]; size <<= 8;
1670 # else
1671 vg_assert((tmp[4] == 0) && (tmp[5] == 0) && (tmp[6] == 0)
1672 && (tmp[7] == 0));
1673 size = 0;
1674 # endif
1675 size += tmp[8]; size <<= 8;
1676 size += tmp[9]; size <<= 8;
1677 size += tmp[10]; size <<= 8;
1678 size += tmp[11];
1679 s->ioff = ML_(img_mark_compressed_part)(s->img,
1680 s->ioff + SIZE_OF_ZLIB_HEADER,
1681 s->szB - SIZE_OF_ZLIB_HEADER,
1682 size);
1683 s->szB = size;
1686 return True;
1689 /* Helper function to get the readlink path. Returns a copy of path if the
1690 file wasn't a symbolic link. Returns NULL on error. Unless NULL is
1691 returned the result needs to be released with dinfo_free.
1693 static HChar* readlink_path (const HChar *path)
1695 SizeT bufsiz = VG_(strlen)(path);
1696 HChar *buf = ML_(dinfo_strdup)("readlink_path.strdup", path);
1697 UInt tries = 6;
1699 while (tries > 0) {
1700 SysRes res;
1701 #if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
1702 res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD,
1703 (UWord)path, (UWord)buf, bufsiz);
1704 #elif defined(VGO_linux) || defined(VGO_darwin)
1705 res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz);
1706 #elif defined(VGO_solaris)
1707 res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD, (UWord)path,
1708 (UWord)buf, bufsiz);
1709 #else
1710 # error Unknown OS
1711 #endif
1712 if (sr_isError(res)) {
1713 if (sr_Err(res) == VKI_EINVAL)
1714 return buf; // It wasn't a symbolic link, return the strdup result.
1715 ML_(dinfo_free)(buf);
1716 return NULL;
1719 SSizeT r = sr_Res(res);
1720 if (r < 0) break;
1721 if (r == bufsiz) { // buffer too small; increase and retry
1722 bufsiz *= 2 + 16;
1723 buf = ML_(dinfo_realloc)("readlink_path.realloc", buf, bufsiz);
1724 tries--;
1725 continue;
1727 buf[r] = '\0';
1728 break;
1731 if (tries == 0) { // We tried, but weird long path?
1732 ML_(dinfo_free)(buf);
1733 return NULL;
1736 if (buf[0] == '/')
1737 return buf;
1739 /* Relative path, add link dir. */
1740 HChar *linkdirptr;
1741 SizeT linkdir_len = VG_(strlen)(path);
1742 if ((linkdirptr = VG_(strrchr)(path, '/')) != NULL)
1743 linkdir_len -= VG_(strlen)(linkdirptr + 1);
1745 SizeT buflen = VG_(strlen)(buf);
1746 SizeT needed = linkdir_len + buflen + 1;
1747 if (bufsiz < needed)
1748 buf = ML_(dinfo_realloc)("readlink_path.linkdir", buf, needed);
1750 VG_(memmove)(buf + linkdir_len, buf, buflen);
1751 VG_(memcpy)(buf, path, linkdir_len);
1752 buf[needed - 1] = '\0';
1754 return buf;
1757 /* The central function for reading ELF debug info. For the
1758 object/exe specified by the DebugInfo, find ELF sections, then read
1759 the symbols, line number info, file name info, CFA (stack-unwind
1760 info) and anything else we want, into the tables within the
1761 supplied DebugInfo.
1764 Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di )
1766 /* This function is long and complex. That, and the presence of
1767 nested scopes, means it's not always easy to see which parts are
1768 in loops/conditionals and which aren't. To make it easier to
1769 follow, points executed exactly once -- that is, those which are
1770 the top level of the function -- are marked TOPLEVEL.
1772 /* Consistent terminology for local variable names, without which
1773 it's almost unfollowably complex:
1775 In which file?
1776 in the main ELF file *_m*
1777 in the debuginfo file *_d*
1778 in the alt debuginfo file *_a*
1780 What kind of thing?
1781 _{m,d,a}img a DiImage*
1782 _{m,d,a}ioff an offset in the image (DiOffT)
1783 _{m,d,a}nent "number of entries"
1784 _{m,d,a}ent_szB "size in bytes of an entry"
1785 ehdr_{m,d,a} ELF header
1786 phdr Program header
1787 shdr Section header
1788 a_X a temporary X
1789 _escn an DiSlice (elf section info) variable
1790 szB size in bytes
1794 /* TOPLEVEL */
1795 Bool res, ok;
1796 Word i, j;
1797 Bool dynbss_present = False;
1798 Bool sdynbss_present = False;
1800 /* Image for the main ELF file we're working with. */
1801 DiImage* mimg = NULL;
1803 /* Ditto for any ELF debuginfo file that we might happen to load. */
1804 DiImage* dimg = NULL;
1806 /* Ditto for alternate ELF debuginfo file that we might happen to load. */
1807 DiImage* aimg = NULL;
1809 /* ELF header offset for the main file. Should be zero since the
1810 ELF header is at start of file. */
1811 DiOffT ehdr_mioff = 0;
1813 /* Program header table image addr, # entries, entry size */
1814 DiOffT phdr_mioff = 0;
1815 UWord phdr_mnent = 0;
1816 UWord phdr_ment_szB = 0;
1818 /* Section header image addr, # entries, entry size. Also the
1819 associated string table. */
1820 DiOffT shdr_mioff = 0;
1821 UWord shdr_mnent = 0;
1822 UWord shdr_ment_szB = 0;
1823 DiOffT shdr_strtab_mioff = 0;
1825 /* SVMAs covered by rx and rw segments and corresponding biases.
1826 Normally each object would provide just one rx and one rw area,
1827 but various ELF mangling tools create objects with multiple
1828 such entries, hence the generality. */
1829 typedef
1830 struct {
1831 Addr svma_base;
1832 Addr svma_limit;
1833 PtrdiffT bias;
1834 Bool exec;
1836 RangeAndBias;
1838 XArray* /* of RangeAndBias */ svma_ranges = NULL;
1840 # if defined(SOLARIS_PT_SUNDWTRACE_THRP)
1841 Addr dtrace_data_vaddr = 0;
1842 # endif
1844 vg_assert(di);
1845 vg_assert(di->fsm.have_rx_map == True);
1846 vg_assert(di->fsm.have_rw_map == True);
1847 vg_assert(di->have_dinfo == False);
1848 vg_assert(di->fsm.filename);
1849 vg_assert(!di->symtab);
1850 vg_assert(!di->loctab);
1851 vg_assert(!di->inltab);
1852 vg_assert(!di->cfsi_base);
1853 vg_assert(!di->cfsi_m_ix);
1854 vg_assert(!di->cfsi_rd);
1855 vg_assert(!di->cfsi_exprs);
1856 vg_assert(!di->strpool);
1857 vg_assert(!di->fndnpool);
1858 vg_assert(!di->soname);
1861 Bool has_nonempty_rx = False;
1862 Bool has_nonempty_rw = False;
1863 for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
1864 DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
1865 if (!map->rx && !map->rw)
1866 continue;
1867 if (map->rx && map->size > 0)
1868 has_nonempty_rx = True;
1869 if (map->rw && map->size > 0)
1870 has_nonempty_rw = True;
1871 /* If this doesn't hold true, it means that m_syswrap/m_aspacemgr
1872 managed to do a mapping where the start isn't page aligned.
1873 Which sounds pretty bogus to me. */
1874 vg_assert(VG_IS_PAGE_ALIGNED(map->avma));
1876 vg_assert(has_nonempty_rx);
1877 vg_assert(has_nonempty_rw);
1880 /* ----------------------------------------------------------
1881 At this point, there is very little information in the
1882 DebugInfo. We only know that something that looks like an ELF
1883 file has been mapped rx-ishly and rw-ishly as recorded in the
1884 di->fsm.maps array items. First we examine the file's ELF
1885 Program Header, and, by comparing that against the di->fsm.maps
1886 info, try to figure out the AVMAs for the sections we care
1887 about, that should have been mapped: text, data, sdata, bss,
1888 got, plt, and toc.
1889 ---------------------------------------------------------- */
1891 res = False;
1893 if (VG_(clo_verbosity) > 1 || VG_(clo_trace_redir))
1894 VG_(message)(Vg_DebugMsg, "Reading syms from %s\n",
1895 di->fsm.filename );
1897 /* Connect to the primary object image, so that we can read symbols
1898 and line number info out of it. It will be disconnected
1899 immediately thereafter; it is only connected transiently. */
1900 mimg = ML_(img_from_local_file)(di->fsm.filename);
1901 if (mimg == NULL) {
1902 VG_(message)(Vg_UserMsg, "warning: connection to image %s failed\n",
1903 di->fsm.filename );
1904 VG_(message)(Vg_UserMsg, " no symbols or debug info loaded\n" );
1905 return False;
1908 /* Ok, the object image is available. Now verify that it is a
1909 valid ELF .so or executable image. */
1910 ok = is_elf_object_file_by_DiImage(mimg, False);
1911 if (!ok) {
1912 ML_(symerr)(di, True, "Invalid ELF Header");
1913 goto out;
1916 /* Find where the program and section header tables are, and give
1917 up if either is missing or outside the image (bogus). */
1918 ElfXX_Ehdr ehdr_m;
1919 vg_assert(ehdr_mioff == 0); // ensured by its initialisation
1920 ok = ML_(img_valid)(mimg, ehdr_mioff, sizeof(ehdr_m));
1921 vg_assert(ok); // ML_(is_elf_object_file) should ensure this
1922 ML_(img_get)(&ehdr_m, mimg, ehdr_mioff, sizeof(ehdr_m));
1924 phdr_mioff = ehdr_mioff + ehdr_m.e_phoff;
1925 phdr_mnent = ehdr_m.e_phnum;
1926 phdr_ment_szB = ehdr_m.e_phentsize;
1928 shdr_mioff = ehdr_mioff + ehdr_m.e_shoff;
1929 shdr_mnent = ehdr_m.e_shnum;
1930 shdr_ment_szB = ehdr_m.e_shentsize;
1932 TRACE_SYMTAB("------ Basic facts about the object ------\n");
1933 TRACE_SYMTAB("object: n_oimage %llu\n",
1934 (ULong)ML_(img_size)(mimg));
1935 TRACE_SYMTAB("phdr: ioff %llu nent %lu ent_szB %lu\n",
1936 phdr_mioff, phdr_mnent, phdr_ment_szB);
1937 TRACE_SYMTAB("shdr: ioff %llu nent %lu ent_szB %lu\n",
1938 shdr_mioff, shdr_mnent, shdr_ment_szB);
1939 for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
1940 const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
1941 if (map->rx)
1942 TRACE_SYMTAB("rx_map: avma %#lx size %lu foff %ld\n",
1943 map->avma, map->size, map->foff);
1945 for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
1946 const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
1947 if (map->rw)
1948 TRACE_SYMTAB("rw_map: avma %#lx size %lu foff %ld\n",
1949 map->avma, map->size, map->foff);
1952 if (phdr_mnent == 0
1953 || !ML_(img_valid)(mimg, phdr_mioff, phdr_mnent * phdr_ment_szB)) {
1954 ML_(symerr)(di, True, "Missing or invalid ELF Program Header Table");
1955 goto out;
1958 if (shdr_mnent == 0
1959 || !ML_(img_valid)(mimg, shdr_mioff, shdr_mnent * shdr_ment_szB)) {
1960 ML_(symerr)(di, True, "Missing or invalid ELF Section Header Table");
1961 goto out;
1964 /* Also find the section header's string table, and validate. */
1965 /* checked previously by is_elf_object_file: */
1966 vg_assert(ehdr_m.e_shstrndx != SHN_UNDEF);
1968 // shdr_mioff is the offset of the section header table
1969 // and we need the ehdr_m.e_shstrndx'th entry
1970 { ElfXX_Shdr a_shdr;
1971 ML_(img_get)(&a_shdr, mimg,
1972 INDEX_BIS(shdr_mioff, ehdr_m.e_shstrndx, shdr_ment_szB),
1973 sizeof(a_shdr));
1974 shdr_strtab_mioff
1975 = ehdr_mioff /* isn't this always zero? */ + a_shdr.sh_offset;
1977 if (!ML_(img_valid)(mimg, shdr_strtab_mioff,
1978 1/*bogus, but we don't know the real size*/ )) {
1979 ML_(symerr)(di, True, "Invalid ELF Section Header String Table");
1980 goto out;
1984 TRACE_SYMTAB("shdr: string table at %llu\n", shdr_strtab_mioff);
1986 svma_ranges = VG_(newXA)(ML_(dinfo_zalloc), "di.relfdi.1",
1987 ML_(dinfo_free), sizeof(RangeAndBias));
1989 /* TOPLEVEL */
1990 /* Look through the program header table, and:
1991 - copy information from suitable PT_LOAD entries into svma_ranges
1992 - find (or fake up) the .soname for this object.
1994 TRACE_SYMTAB("\n");
1995 TRACE_SYMTAB("------ Examining the program headers ------\n");
1996 vg_assert(di->soname == NULL);
1998 /* TOPLEVEL */
1999 ElfXX_Addr prev_svma = 0;
2001 for (i = 0; i < phdr_mnent; i++) {
2002 ElfXX_Phdr a_phdr;
2003 ML_(img_get)(&a_phdr, mimg,
2004 INDEX_BIS(phdr_mioff, i, phdr_ment_szB),
2005 sizeof(a_phdr));
2007 /* Make sure the PT_LOADable entries are in order and
2008 non-overlapping. This in turn means the address ranges
2009 slurped into svma_ranges are in order and
2010 non-overlapping. */
2012 if (a_phdr.p_type == PT_LOAD) {
2013 TRACE_SYMTAB("PT_LOAD[%ld]: p_vaddr %#lx (prev %#lx)\n",
2014 i, (UWord)a_phdr.p_vaddr, (UWord)prev_svma);
2015 TRACE_SYMTAB("PT_LOAD[%ld]: p_offset %lu, p_filesz %lu,"
2016 " perms %c%c%c\n",
2017 i, (UWord)a_phdr.p_offset, (UWord)a_phdr.p_filesz,
2018 a_phdr.p_flags & PF_R ? 'r' : '-',
2019 a_phdr.p_flags & PF_W ? 'w' : '-',
2020 a_phdr.p_flags & PF_X ? 'x' : '-');
2021 if (a_phdr.p_vaddr < prev_svma) {
2022 ML_(symerr)(di, True,
2023 "ELF Program Headers are not in ascending order");
2024 goto out;
2026 prev_svma = a_phdr.p_vaddr;
2027 if (a_phdr.p_memsz > 0) {
2028 Bool loaded = False;
2029 for (j = 0; j < VG_(sizeXA)(di->fsm.maps); j++) {
2030 const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, j);
2031 if ( (map->rx || map->rw || map->ro)
2032 && map->size > 0 /* stay sane */
2033 && a_phdr.p_offset >= map->foff
2034 && a_phdr.p_offset < map->foff + map->size
2035 && a_phdr.p_offset + a_phdr.p_filesz
2036 <= map->foff + map->size) {
2037 RangeAndBias item;
2038 item.svma_base = a_phdr.p_vaddr;
2039 item.svma_limit = a_phdr.p_vaddr + a_phdr.p_memsz;
2040 item.bias = map->avma - map->foff
2041 + a_phdr.p_offset - a_phdr.p_vaddr;
2042 if (map->rw
2043 && (a_phdr.p_flags & (PF_R | PF_W))
2044 == (PF_R | PF_W)) {
2045 item.exec = False;
2046 VG_(addToXA)(svma_ranges, &item);
2047 TRACE_SYMTAB(
2048 "PT_LOAD[%ld]: acquired as rw, bias 0x%lx\n",
2049 i, (UWord)item.bias);
2050 loaded = True;
2052 if (map->rx
2053 && (a_phdr.p_flags & (PF_R | PF_X))
2054 == (PF_R | PF_X)) {
2055 item.exec = True;
2056 VG_(addToXA)(svma_ranges, &item);
2057 TRACE_SYMTAB(
2058 "PT_LOAD[%ld]: acquired as rx, bias 0x%lx\n",
2059 i, (UWord)item.bias);
2060 loaded = True;
2062 if (map->ro
2063 && (a_phdr.p_flags & (PF_R | PF_W | PF_X))
2064 == PF_R) {
2065 item.exec = False;
2066 VG_(addToXA)(svma_ranges, &item);
2067 TRACE_SYMTAB(
2068 "PT_LOAD[%ld]: acquired as ro, bias 0x%lx\n",
2069 i, (UWord)item.bias);
2070 loaded = True;
2074 if (!loaded) {
2075 # if defined(SOLARIS_PT_SUNDWTRACE_THRP)
2076 if ((a_phdr.p_memsz == VKI_PT_SUNWDTRACE_SIZE)
2077 && ((a_phdr.p_flags & (PF_R | PF_W | PF_X)) == PF_R)) {
2078 TRACE_SYMTAB("PT_LOAD[%ld]: ignore dtrace_data program "
2079 "header\n", i);
2080 dtrace_data_vaddr = a_phdr.p_vaddr;
2081 continue;
2083 # endif /* SOLARIS_PT_SUNDWTRACE_THRP */
2085 ML_(symerr)(di, False,
2086 "ELF section outside all mapped regions");
2087 /* This problem might be solved by further memory mappings.
2088 Avoid the vg_assert(!di->soname) at the beginning of this
2089 function if DYNAMIC section has been already processed. */
2090 if (di->soname) {
2091 ML_(dinfo_free)(di->soname);
2092 di->soname = NULL;
2094 goto out;
2099 /* Try to get the soname. If there isn't one, use "NONE".
2100 The seginfo needs to have some kind of soname in order to
2101 facilitate writing redirect functions, since all redirect
2102 specifications require a soname (pattern). */
2103 if (a_phdr.p_type == PT_DYNAMIC && di->soname == NULL) {
2104 Word stroff = -1;
2105 DiOffT strtab_mioff = DiOffT_INVALID;
2106 for (j = 0; True/*exit check is in the loop*/; j++) {
2107 ElfXX_Dyn t_dyn_m; /* dyn_img[j] */
2108 ML_(img_get)(&t_dyn_m, mimg,
2109 INDEX_BIS(ehdr_mioff + a_phdr.p_offset,
2110 j, sizeof(ElfXX_Dyn)),
2111 sizeof(t_dyn_m));
2112 if (t_dyn_m.d_tag == DT_NULL)
2113 break;
2115 switch (t_dyn_m.d_tag) {
2116 case DT_SONAME: {
2117 stroff = t_dyn_m.d_un.d_val;
2118 break;
2120 case DT_STRTAB: {
2121 Bool ok2 = False;
2122 Word offset = file_offset_from_svma(
2123 &ok2, t_dyn_m.d_un.d_ptr, mimg,
2124 phdr_mioff, phdr_mnent, phdr_ment_szB
2126 if (ok2 && strtab_mioff == DiOffT_INVALID) {
2127 // Check for obviously bogus offsets.
2128 if (!ML_(img_valid)(mimg, offset, 1)) {
2129 ML_(symerr)(di, True, "Invalid DT_STRTAB offset");
2130 goto out;
2132 strtab_mioff = ehdr_mioff + offset;
2133 vg_assert(ehdr_mioff == 0); // should always be
2135 break;
2137 default:
2138 break;
2141 if (stroff != -1 && strtab_mioff != DiOffT_INVALID) {
2142 di->soname = ML_(img_strdup)(mimg, "di.redi.1",
2143 strtab_mioff + stroff);
2144 TRACE_SYMTAB("Found soname = %s\n", di->soname);
2147 } /* for (i = 0; i < phdr_Mnent; i++) ... */
2148 /* TOPLEVEL */
2150 } /* examine the program headers (local scope) */
2152 /* TOPLEVEL */
2154 /* If, after looking at all the program headers, we still didn't
2155 find a soname, add a fake one. */
2156 if (di->soname == NULL) {
2157 TRACE_SYMTAB("No soname found; using (fake) \"NONE\"\n");
2158 di->soname = ML_(dinfo_strdup)("di.redi.2", "NONE");
2161 vg_assert(VG_(sizeXA)(svma_ranges) != 0);
2163 /* Now read the section table. */
2164 TRACE_SYMTAB("\n");
2165 TRACE_SYMTAB("------ Examining the section headers ------\n");
2166 for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
2167 const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
2168 if (map->rx)
2169 TRACE_SYMTAB("rx: at %#lx are mapped foffsets %ld .. %lu\n",
2170 map->avma, map->foff, map->foff + map->size - 1 );
2172 TRACE_SYMTAB("rx: contains these svma regions:\n");
2173 for (i = 0; i < VG_(sizeXA)(svma_ranges); i++) {
2174 const RangeAndBias* reg = VG_(indexXA)(svma_ranges, i);
2175 if (reg->exec)
2176 TRACE_SYMTAB(" svmas %#lx .. %#lx with bias %#lx\n",
2177 reg->svma_base, reg->svma_limit - 1, (UWord)reg->bias );
2179 for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
2180 const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
2181 if (map->rw)
2182 TRACE_SYMTAB("rw: at %#lx are mapped foffsets %ld .. %lu\n",
2183 map->avma, map->foff, map->foff + map->size - 1 );
2185 TRACE_SYMTAB("rw: contains these svma regions:\n");
2186 for (i = 0; i < VG_(sizeXA)(svma_ranges); i++) {
2187 const RangeAndBias* reg = VG_(indexXA)(svma_ranges, i);
2188 if (!reg->exec)
2189 TRACE_SYMTAB(" svmas %#lx .. %#lx with bias %#lx\n",
2190 reg->svma_base, reg->svma_limit - 1, (UWord)reg->bias );
2193 /* TOPLEVEL */
2194 /* Iterate over section headers */
2195 for (i = 0; i < shdr_mnent; i++) {
2196 ElfXX_Shdr a_shdr;
2197 ML_(img_get)(&a_shdr, mimg,
2198 INDEX_BIS(shdr_mioff, i, shdr_ment_szB), sizeof(a_shdr));
2199 DiOffT name_mioff = shdr_strtab_mioff + a_shdr.sh_name;
2200 HChar* name = ML_(img_strdup)(mimg, "di.redi_name.2", name_mioff);
2201 Addr svma = a_shdr.sh_addr;
2202 OffT foff = a_shdr.sh_offset;
2203 UWord size = a_shdr.sh_size; /* Do not change this to be signed. */
2204 UInt alyn = a_shdr.sh_addralign;
2205 Bool nobits = a_shdr.sh_type == SHT_NOBITS;
2206 /* Look through our collection of info obtained from the PT_LOAD
2207 headers, and make 'inrx' and 'inrw' point to the first entry
2208 in each that intersects 'avma'. If in each case none is found,
2209 leave the relevant pointer at NULL. */
2210 RangeAndBias* inrx = NULL;
2211 RangeAndBias* inrw = NULL;
2212 for (j = 0; j < VG_(sizeXA)(svma_ranges); j++) {
2213 RangeAndBias* rng = VG_(indexXA)(svma_ranges, j);
2214 if (svma >= rng->svma_base && svma < rng->svma_limit) {
2215 if (!inrx && rng->exec) {
2216 inrx = rng;
2217 } else if (!inrw && !rng->exec) {
2218 inrw = rng;
2220 if (inrx && inrw)
2221 break;
2225 TRACE_SYMTAB(" [sec %2ld] %s %s al%4u foff %6ld .. %6lu "
2226 " svma %p name \"%s\"\n",
2227 i, inrx ? "rx" : " ", inrw ? "rw" : " ", alyn,
2228 foff, (size == 0) ? foff : foff+size-1, (void *) svma, name);
2230 /* Check for sane-sized segments. SHT_NOBITS sections have zero
2231 size in the file and their offsets are just conceptual. */
2232 if (!nobits &&
2233 (foff >= ML_(img_size)(mimg) || foff + size > ML_(img_size)(mimg))) {
2234 ML_(symerr)(di, True, "ELF Section extends beyond image end");
2235 goto out;
2238 /* Check for a sane alignment value. */
2239 if (alyn > 0 && -1 == VG_(log2)(alyn)) {
2240 ML_(symerr)(di, True, "ELF Section contains invalid "
2241 ".sh_addralign value");
2242 goto out;
2245 /* Ignore zero sized sections. */
2246 if (size == 0) {
2247 TRACE_SYMTAB("zero sized section \"%s\", ignoring\n", name);
2248 ML_(dinfo_free)(name);
2249 continue;
2252 # define BAD(_secname) \
2253 do { ML_(symerr)(di, True, \
2254 "Can't make sense of " _secname \
2255 " section mapping"); \
2256 /* make sure we don't assert if we find */ \
2257 /* ourselves back in this routine later, */ \
2258 /* with the same di */ \
2259 di->soname = NULL; \
2260 goto out; \
2261 } while (0)
2263 /* Find avma-s for: .text .data .sdata .rodata .bss .sbss .plt .got .opd
2264 and .eh_frame */
2266 /* Accept .text where mapped as rx (code), even if zero-sized */
2267 if (0 == VG_(strcmp)(name, ".text")) {
2268 if (inrx && !di->text_present) {
2269 di->text_present = True;
2270 di->text_svma = svma;
2271 di->text_avma = svma + inrx->bias;
2272 di->text_size = size;
2273 di->text_bias = inrx->bias;
2274 di->text_debug_svma = svma;
2275 di->text_debug_bias = inrx->bias;
2276 TRACE_SYMTAB("acquiring .text svma = %#lx .. %#lx\n",
2277 di->text_svma,
2278 di->text_svma + di->text_size - 1);
2279 TRACE_SYMTAB("acquiring .text avma = %#lx .. %#lx\n",
2280 di->text_avma,
2281 di->text_avma + di->text_size - 1);
2282 TRACE_SYMTAB("acquiring .text bias = %#lx\n", (UWord)di->text_bias);
2283 } else {
2284 BAD(".text");
2288 /* Accept .data where mapped as rw (data), even if zero-sized */
2289 if (0 == VG_(strcmp)(name, ".data")) {
2290 # if defined(SOLARIS_PT_SUNDWTRACE_THRP)
2291 if ((size == VKI_PT_SUNWDTRACE_SIZE) && (svma == dtrace_data_vaddr)) {
2292 TRACE_SYMTAB("ignoring .data section for dtrace_data "
2293 "%#lx .. %#lx\n", svma, svma + size - 1);
2294 } else
2295 # endif /* SOLARIS_PT_SUNDWTRACE_THRP */
2296 if (inrw && !di->data_present) {
2297 di->data_present = True;
2298 di->data_svma = svma;
2299 di->data_avma = svma + inrw->bias;
2300 di->data_size = size;
2301 di->data_bias = inrw->bias;
2302 di->data_debug_svma = svma;
2303 di->data_debug_bias = inrw->bias;
2304 TRACE_SYMTAB("acquiring .data svma = %#lx .. %#lx\n",
2305 di->data_svma,
2306 di->data_svma + di->data_size - 1);
2307 TRACE_SYMTAB("acquiring .data avma = %#lx .. %#lx\n",
2308 di->data_avma,
2309 di->data_avma + di->data_size - 1);
2310 TRACE_SYMTAB("acquiring .data bias = %#lx\n", (UWord)di->data_bias);
2311 } else {
2312 BAD(".data");
2316 /* Accept .sdata where mapped as rw (data) */
2317 if (0 == VG_(strcmp)(name, ".sdata")) {
2318 if (inrw && !di->sdata_present) {
2319 di->sdata_present = True;
2320 di->sdata_svma = svma;
2321 di->sdata_avma = svma + inrw->bias;
2322 di->sdata_size = size;
2323 di->sdata_bias = inrw->bias;
2324 di->sdata_debug_svma = svma;
2325 di->sdata_debug_bias = inrw->bias;
2326 TRACE_SYMTAB("acquiring .sdata svma = %#lx .. %#lx\n",
2327 di->sdata_svma,
2328 di->sdata_svma + di->sdata_size - 1);
2329 TRACE_SYMTAB("acquiring .sdata avma = %#lx .. %#lx\n",
2330 di->sdata_avma,
2331 di->sdata_avma + di->sdata_size - 1);
2332 TRACE_SYMTAB("acquiring .sdata bias = %#lx\n",
2333 (UWord)di->sdata_bias);
2334 } else {
2335 BAD(".sdata");
2339 /* Accept .rodata where mapped as rx or rw (data), even if zero-sized */
2340 if (0 == VG_(strcmp)(name, ".rodata")) {
2341 if (!di->rodata_present) {
2342 di->rodata_svma = svma;
2343 di->rodata_avma = svma;
2344 di->rodata_size = size;
2345 di->rodata_debug_svma = svma;
2346 if (inrx) {
2347 di->rodata_avma += inrx->bias;
2348 di->rodata_bias = inrx->bias;
2349 di->rodata_debug_bias = inrx->bias;
2350 } else if (inrw) {
2351 di->rodata_avma += inrw->bias;
2352 di->rodata_bias = inrw->bias;
2353 di->rodata_debug_bias = inrw->bias;
2354 } else {
2355 BAD(".rodata");
2357 di->rodata_present = True;
2358 TRACE_SYMTAB("acquiring .rodata svma = %#lx .. %#lx\n",
2359 di->rodata_svma,
2360 di->rodata_svma + di->rodata_size - 1);
2361 TRACE_SYMTAB("acquiring .rodata avma = %#lx .. %#lx\n",
2362 di->rodata_avma,
2363 di->rodata_avma + di->rodata_size - 1);
2364 TRACE_SYMTAB("acquiring .rodata bias = %#lx\n",
2365 (UWord)di->rodata_bias);
2366 } else {
2367 BAD(".rodata");
2371 if (0 == VG_(strcmp)(name, ".dynbss")) {
2372 if (inrw && !di->bss_present) {
2373 dynbss_present = True;
2374 di->bss_present = True;
2375 di->bss_svma = svma;
2376 di->bss_avma = svma + inrw->bias;
2377 di->bss_size = size;
2378 di->bss_bias = inrw->bias;
2379 di->bss_debug_svma = svma;
2380 di->bss_debug_bias = inrw->bias;
2381 TRACE_SYMTAB("acquiring .dynbss svma = %#lx .. %#lx\n",
2382 di->bss_svma,
2383 di->bss_svma + di->bss_size - 1);
2384 TRACE_SYMTAB("acquiring .dynbss avma = %#lx .. %#lx\n",
2385 di->bss_avma,
2386 di->bss_avma + di->bss_size - 1);
2387 TRACE_SYMTAB("acquiring .dynbss bias = %#lx\n",
2388 (UWord)di->bss_bias);
2392 /* Accept .bss where mapped as rw (data), even if zero-sized */
2393 if (0 == VG_(strcmp)(name, ".bss")) {
2394 if (inrw && dynbss_present) {
2395 vg_assert(di->bss_present);
2396 dynbss_present = False;
2397 vg_assert(di->bss_svma + di->bss_size == svma);
2398 di->bss_size += size;
2399 TRACE_SYMTAB("acquiring .bss svma = %#lx .. %#lx\n",
2400 svma, svma + size - 1);
2401 TRACE_SYMTAB("acquiring .bss avma = %#lx .. %#lx\n",
2402 svma + inrw->bias, svma + inrw->bias + size - 1);
2403 TRACE_SYMTAB("acquiring .bss bias = %#lx\n",
2404 (UWord)di->bss_bias);
2405 } else
2407 if (inrw && !di->bss_present) {
2408 di->bss_present = True;
2409 di->bss_svma = svma;
2410 di->bss_avma = svma + inrw->bias;
2411 di->bss_size = size;
2412 di->bss_bias = inrw->bias;
2413 di->bss_debug_svma = svma;
2414 di->bss_debug_bias = inrw->bias;
2415 TRACE_SYMTAB("acquiring .bss svma = %#lx .. %#lx\n",
2416 di->bss_svma,
2417 di->bss_svma + di->bss_size - 1);
2418 TRACE_SYMTAB("acquiring .bss avma = %#lx .. %#lx\n",
2419 di->bss_avma,
2420 di->bss_avma + di->bss_size - 1);
2421 TRACE_SYMTAB("acquiring .bss bias = %#lx\n",
2422 (UWord)di->bss_bias);
2423 } else
2425 /* Now one from the wtf?! department ... */
2426 if (inrx && (!inrw) && !di->bss_present) {
2427 /* File contains a .bss, but it got mapped as rx only.
2428 This is very strange. For now, just pretend we didn't
2429 see it :-) */
2430 di->bss_present = False;
2431 di->bss_svma = 0;
2432 di->bss_avma = 0;
2433 di->bss_size = 0;
2434 di->bss_bias = 0;
2435 di->bss_debug_svma = 0;
2436 di->bss_debug_bias = 0;
2437 if (!VG_(clo_xml)) {
2438 VG_(message)(Vg_UserMsg,
2439 "Warning: the following file's .bss is "
2440 "mapped r-x only - ignoring .bss syms\n");
2441 VG_(message)(Vg_UserMsg, " %s\n", di->fsm.filename
2442 ? di->fsm.filename
2443 : "(null?!)" );
2445 } else
2447 if ((!inrw) && (!inrx) && !di->bss_present) {
2448 /* File contains a .bss, but it didn't get mapped. Ignore. */
2449 di->bss_present = False;
2450 di->bss_svma = 0;
2451 di->bss_avma = 0;
2452 di->bss_size = 0;
2453 di->bss_bias = 0;
2454 } else {
2455 BAD(".bss");
2459 if (0 == VG_(strcmp)(name, ".sdynbss")) {
2460 if (inrw && !di->sbss_present) {
2461 sdynbss_present = True;
2462 di->sbss_present = True;
2463 di->sbss_svma = svma;
2464 di->sbss_avma = svma + inrw->bias;
2465 di->sbss_size = size;
2466 di->sbss_bias = inrw->bias;
2467 di->sbss_debug_svma = svma;
2468 di->sbss_debug_bias = inrw->bias;
2469 TRACE_SYMTAB("acquiring .sdynbss svma = %#lx .. %#lx\n",
2470 di->sbss_svma,
2471 di->sbss_svma + di->sbss_size - 1);
2472 TRACE_SYMTAB("acquiring .sdynbss avma = %#lx .. %#lx\n",
2473 di->sbss_avma,
2474 di->sbss_avma + di->sbss_size - 1);
2475 TRACE_SYMTAB("acquiring .sdynbss bias = %#lx\n",
2476 (UWord)di->sbss_bias);
2480 /* Accept .sbss where mapped as rw (data) */
2481 if (0 == VG_(strcmp)(name, ".sbss")) {
2482 if (inrw && sdynbss_present) {
2483 vg_assert(di->sbss_present);
2484 sdynbss_present = False;
2485 vg_assert(di->sbss_svma + di->sbss_size == svma);
2486 di->sbss_size += size;
2487 TRACE_SYMTAB("acquiring .sbss svma = %#lx .. %#lx\n",
2488 svma, svma + size - 1);
2489 TRACE_SYMTAB("acquiring .sbss avma = %#lx .. %#lx\n",
2490 svma + inrw->bias, svma + inrw->bias + size - 1);
2491 TRACE_SYMTAB("acquiring .sbss bias = %#lx\n", (UWord)di->sbss_bias);
2492 } else
2494 if (inrw && !di->sbss_present) {
2495 di->sbss_present = True;
2496 di->sbss_svma = svma;
2497 di->sbss_avma = svma + inrw->bias;
2498 di->sbss_size = size;
2499 di->sbss_bias = inrw->bias;
2500 di->sbss_debug_svma = svma;
2501 di->sbss_debug_bias = inrw->bias;
2502 TRACE_SYMTAB("acquiring .sbss svma = %#lx .. %#lx\n",
2503 di->sbss_svma,
2504 di->sbss_svma + di->sbss_size - 1);
2505 TRACE_SYMTAB("acquiring .sbss avma = %#lx .. %#lx\n",
2506 di->sbss_avma,
2507 di->sbss_avma + di->sbss_size - 1);
2508 TRACE_SYMTAB("acquiring .sbss bias = %#lx\n", (UWord)di->sbss_bias);
2509 } else {
2510 BAD(".sbss");
2514 /* Accept .got where mapped as rw (data) */
2515 if (0 == VG_(strcmp)(name, ".got")) {
2516 if (inrw && !di->got_present) {
2517 di->got_present = True;
2518 di->got_avma = svma + inrw->bias;
2519 di->got_size = size;
2520 TRACE_SYMTAB("acquiring .got avma = %#lx\n", di->got_avma);
2521 } else {
2522 BAD(".got");
2526 /* Accept .got.plt where mapped as rw (data) */
2527 if (0 == VG_(strcmp)(name, ".got.plt")) {
2528 if (inrw && !di->gotplt_present) {
2529 di->gotplt_present = True;
2530 di->gotplt_avma = svma + inrw->bias;
2531 di->gotplt_size = size;
2532 TRACE_SYMTAB("acquiring .got.plt avma = %#lx\n", di->gotplt_avma);
2533 } else if (size != 0) {
2534 BAD(".got.plt");
2538 /* PLT is different on different platforms, it seems. */
2539 # if defined(VGP_x86_linux) || defined(VGP_amd64_linux) \
2540 || defined(VGP_arm_linux) || defined (VGP_s390x_linux) \
2541 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
2542 || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
2543 || defined(VGP_x86_solaris) || defined(VGP_amd64_solaris)
2544 /* Accept .plt where mapped as rx (code) */
2545 if (0 == VG_(strcmp)(name, ".plt")) {
2546 if (inrx && !di->plt_present) {
2547 di->plt_present = True;
2548 di->plt_avma = svma + inrx->bias;
2549 di->plt_size = size;
2550 TRACE_SYMTAB("acquiring .plt avma = %#lx\n", di->plt_avma);
2551 } else {
2552 BAD(".plt");
2555 # elif defined(VGP_ppc32_linux)
2556 /* Accept .plt where mapped as rw (data) */
2557 if (0 == VG_(strcmp)(name, ".plt")) {
2558 if (inrw && !di->plt_present) {
2559 di->plt_present = True;
2560 di->plt_avma = svma + inrw->bias;
2561 di->plt_size = size;
2562 TRACE_SYMTAB("acquiring .plt avma = %#lx\n", di->plt_avma);
2563 } else {
2564 BAD(".plt");
2567 # elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
2568 /* Accept .plt where mapped as rw (data), or unmapped */
2569 if (0 == VG_(strcmp)(name, ".plt")) {
2570 if (inrw && !di->plt_present) {
2571 di->plt_present = True;
2572 di->plt_avma = svma + inrw->bias;
2573 di->plt_size = size;
2574 TRACE_SYMTAB("acquiring .plt avma = %#lx\n", di->plt_avma);
2575 } else
2576 if ((!inrw) && (!inrx) && size > 0 && !di->plt_present) {
2577 /* File contains a .plt, but it didn't get mapped.
2578 Presumably it is not required on this platform. At
2579 least don't reject the situation as invalid. */
2580 di->plt_present = True;
2581 di->plt_avma = 0;
2582 di->plt_size = 0;
2583 } else {
2584 BAD(".plt");
2587 # else
2588 # error "Unsupported platform"
2589 # endif
2591 /* Accept .opd where mapped as rw (data) */
2592 if (0 == VG_(strcmp)(name, ".opd")) {
2593 if (inrw && !di->opd_present) {
2594 di->opd_present = True;
2595 di->opd_avma = svma + inrw->bias;
2596 di->opd_size = size;
2597 TRACE_SYMTAB("acquiring .opd avma = %#lx\n", di->opd_avma);
2598 } else {
2599 BAD(".opd");
2603 /* Accept .eh_frame where mapped as rx (code). This seems to be
2604 the common case. However, if that doesn't pan out, try for
2605 rw (data) instead. We can handle up to N_EHFRAME_SECTS per
2606 ELF object. */
2607 if (0 == VG_(strcmp)(name, ".eh_frame")) {
2608 if (inrx && di->n_ehframe < N_EHFRAME_SECTS) {
2609 di->ehframe_avma[di->n_ehframe] = svma + inrx->bias;
2610 di->ehframe_size[di->n_ehframe] = size;
2611 TRACE_SYMTAB("acquiring .eh_frame avma = %#lx\n",
2612 di->ehframe_avma[di->n_ehframe]);
2613 di->n_ehframe++;
2614 } else
2615 if (inrw && di->n_ehframe < N_EHFRAME_SECTS) {
2616 di->ehframe_avma[di->n_ehframe] = svma + inrw->bias;
2617 di->ehframe_size[di->n_ehframe] = size;
2618 TRACE_SYMTAB("acquiring .eh_frame avma = %#lx\n",
2619 di->ehframe_avma[di->n_ehframe]);
2620 di->n_ehframe++;
2621 } else {
2622 BAD(".eh_frame");
2626 /* Accept .ARM.exidx where mapped as rx (code). */
2627 /* FIXME: make sure the entire section is mapped in, not just
2628 the first address. */
2629 if (0 == VG_(strcmp)(name, ".ARM.exidx")) {
2630 if (inrx && !di->exidx_present) {
2631 di->exidx_present = True;
2632 di->exidx_svma = svma;
2633 di->exidx_avma = svma + inrx->bias;
2634 di->exidx_size = size;
2635 di->exidx_bias = inrx->bias;
2636 TRACE_SYMTAB("acquiring .exidx svma = %#lx .. %#lx\n",
2637 di->exidx_svma,
2638 di->exidx_svma + di->exidx_size - 1);
2639 TRACE_SYMTAB("acquiring .exidx avma = %#lx .. %#lx\n",
2640 di->exidx_avma,
2641 di->exidx_avma + di->exidx_size - 1);
2642 TRACE_SYMTAB("acquiring .exidx bias = %#lx\n",
2643 (UWord)di->exidx_bias);
2644 } else {
2645 BAD(".ARM.exidx");
2649 /* Accept .ARM.extab where mapped as rx (code). */
2650 /* FIXME: make sure the entire section is mapped in, not just
2651 the first address. */
2652 if (0 == VG_(strcmp)(name, ".ARM.extab")) {
2653 if (inrx && !di->extab_present) {
2654 di->extab_present = True;
2655 di->extab_svma = svma;
2656 di->extab_avma = svma + inrx->bias;
2657 di->extab_size = size;
2658 di->extab_bias = inrx->bias;
2659 TRACE_SYMTAB("acquiring .extab svma = %#lx .. %#lx\n",
2660 di->extab_svma,
2661 di->extab_svma + di->extab_size - 1);
2662 TRACE_SYMTAB("acquiring .extab avma = %#lx .. %#lx\n",
2663 di->extab_avma,
2664 di->extab_avma + di->extab_size - 1);
2665 TRACE_SYMTAB("acquiring .extab bias = %#lx\n",
2666 (UWord)di->extab_bias);
2667 } else {
2668 BAD(".ARM.extab");
2672 ML_(dinfo_free)(name);
2674 # undef BAD
2676 } /* iterate over the section headers */
2678 /* TOPLEVEL */
2679 if (0) VG_(printf)("YYYY text_: avma %#lx size %lu bias %#lx\n",
2680 di->text_avma, di->text_size, (UWord)di->text_bias);
2682 if (VG_(clo_verbosity) > 2 || VG_(clo_trace_redir))
2683 VG_(message)(Vg_DebugMsg, " svma %#010lx, avma %#010lx\n",
2684 di->text_avma - di->text_bias,
2685 di->text_avma );
2687 TRACE_SYMTAB("\n");
2688 TRACE_SYMTAB("------ Finding image addresses "
2689 "for debug-info sections ------\n");
2691 /* TOPLEVEL */
2692 /* Find interesting sections, read the symbol table(s), read any
2693 debug information. Each section is located either in the main,
2694 debug or alt-debug files, but only in one. For each section,
2695 |section_escn| records which of |mimg|, |dimg| or |aimg| we
2696 found it in, along with the section's image offset and its size.
2697 The triples (section_img, section_ioff, section_szB) are
2698 consistent, in that they are always either (NULL,
2699 DiOffT_INVALID, 0), or refer to the same image, and are all
2700 assigned together. */
2702 /* TOPLEVEL */
2703 DiSlice strtab_escn = DiSlice_INVALID; // .strtab
2704 DiSlice symtab_escn = DiSlice_INVALID; // .symtab
2705 DiSlice dynstr_escn = DiSlice_INVALID; // .dynstr
2706 DiSlice dynsym_escn = DiSlice_INVALID; // .dynsym
2707 # if defined(VGO_solaris)
2708 DiSlice ldynsym_escn = DiSlice_INVALID; // .SUNW_ldynsym
2709 # endif
2710 DiSlice debuglink_escn = DiSlice_INVALID; // .gnu_debuglink
2711 DiSlice debugaltlink_escn = DiSlice_INVALID; // .gnu_debugaltlink
2712 DiSlice debug_line_escn = DiSlice_INVALID; // .debug_line (dwarf2)
2713 DiSlice debug_info_escn = DiSlice_INVALID; // .debug_info (dwarf2)
2714 DiSlice debug_types_escn = DiSlice_INVALID; // .debug_types (dwarf4)
2715 DiSlice debug_abbv_escn = DiSlice_INVALID; // .debug_abbrev (dwarf2)
2716 DiSlice debug_str_escn = DiSlice_INVALID; // .debug_str (dwarf2)
2717 DiSlice debug_line_str_escn = DiSlice_INVALID; // .debug_line_str(dwarf5)
2718 DiSlice debug_ranges_escn = DiSlice_INVALID; // .debug_ranges (dwarf2)
2719 DiSlice debug_rnglists_escn = DiSlice_INVALID; // .debug_rnglists(dwarf5)
2720 DiSlice debug_loclists_escn = DiSlice_INVALID; // .debug_loclists(dwarf5)
2721 DiSlice debug_loc_escn = DiSlice_INVALID; // .debug_loc (dwarf2)
2722 DiSlice debug_frame_escn = DiSlice_INVALID; // .debug_frame (dwarf2)
2723 DiSlice debug_line_alt_escn = DiSlice_INVALID; // .debug_line (alt)
2724 DiSlice debug_info_alt_escn = DiSlice_INVALID; // .debug_info (alt)
2725 DiSlice debug_abbv_alt_escn = DiSlice_INVALID; // .debug_abbrev (alt)
2726 DiSlice debug_str_alt_escn = DiSlice_INVALID; // .debug_str (alt)
2727 DiSlice dwarf1d_escn = DiSlice_INVALID; // .debug (dwarf1)
2728 DiSlice dwarf1l_escn = DiSlice_INVALID; // .line (dwarf1)
2729 DiSlice opd_escn = DiSlice_INVALID; // .opd (dwarf2,
2730 // ppc64be-linux)
2731 DiSlice ehframe_escn[N_EHFRAME_SECTS]; // .eh_frame (dwarf2)
2733 for (i = 0; i < N_EHFRAME_SECTS; i++)
2734 ehframe_escn[i] = DiSlice_INVALID;
2736 /* Find all interesting sections */
2738 UInt ehframe_mix = 0;
2740 /* What FIND does: it finds the section called _SEC_NAME. The
2741 size of it is assigned to _SEC_SIZE. The address of the
2742 section in the transiently loaded oimage is assigned to
2743 _SEC_IMG. If the section is found, _POST_FX is executed
2744 after _SEC_NAME and _SEC_SIZE have been assigned to.
2746 Even for sections which are marked loadable, the client's
2747 ld.so may not have loaded them yet, so there is no guarantee
2748 that we can safely prod around in any such area). Because
2749 the entire object file is transiently mapped aboard for
2750 inspection, it's always safe to inspect that area. */
2752 /* TOPLEVEL */
2753 /* Iterate over section headers (again) */
2754 for (i = 0; i < ehdr_m.e_shnum; i++) {
2756 # define FINDX(_sec_name, _sec_escn, _post_fx) \
2757 do { \
2758 ElfXX_Shdr a_shdr; \
2759 ML_(img_get)(&a_shdr, mimg, \
2760 INDEX_BIS(shdr_mioff, i, shdr_ment_szB), \
2761 sizeof(a_shdr)); \
2762 if (0 == ML_(img_strcmp_c)(mimg, shdr_strtab_mioff \
2763 + a_shdr.sh_name, _sec_name)) { \
2764 Bool nobits; \
2765 _sec_escn.img = mimg; \
2766 _sec_escn.ioff = (DiOffT)a_shdr.sh_offset; \
2767 _sec_escn.szB = a_shdr.sh_size; \
2768 if (!check_compression(&a_shdr, &_sec_escn)) { \
2769 ML_(symerr)(di, True, " Compression type is unsupported"); \
2770 goto out; \
2772 nobits = a_shdr.sh_type == SHT_NOBITS; \
2773 vg_assert(_sec_escn.img != NULL); \
2774 vg_assert(_sec_escn.ioff != DiOffT_INVALID); \
2775 TRACE_SYMTAB( "%-18s: ioff %llu .. %llu\n", \
2776 _sec_name, (ULong)a_shdr.sh_offset, \
2777 ((ULong)a_shdr.sh_offset) + a_shdr.sh_size - 1); \
2778 /* SHT_NOBITS sections have zero size in the file. */ \
2779 if (!nobits && \
2780 a_shdr.sh_offset + \
2781 a_shdr.sh_size > ML_(img_real_size)(mimg)) { \
2782 ML_(symerr)(di, True, \
2783 " section beyond image end?!"); \
2784 goto out; \
2786 _post_fx; \
2788 } while (0);
2790 /* Version with no post-effects */
2791 # define FIND(_sec_name, _sec_escn) \
2792 FINDX(_sec_name, _sec_escn, /**/)
2794 /* NAME ElfSec */
2795 FIND( ".dynsym", dynsym_escn)
2796 FIND( ".dynstr", dynstr_escn)
2797 FIND( ".symtab", symtab_escn)
2798 FIND( ".strtab", strtab_escn)
2799 # if defined(VGO_solaris)
2800 FIND( ".SUNW_ldynsym", ldynsym_escn)
2801 # endif
2803 FIND( ".gnu_debuglink", debuglink_escn)
2804 FIND( ".gnu_debugaltlink", debugaltlink_escn)
2806 FIND( ".debug_line", debug_line_escn)
2807 if (!ML_(sli_is_valid)(debug_line_escn))
2808 FIND(".zdebug_line", debug_line_escn)
2810 FIND( ".debug_info", debug_info_escn)
2811 if (!ML_(sli_is_valid)(debug_info_escn))
2812 FIND(".zdebug_info", debug_info_escn)
2814 FIND( ".debug_types", debug_types_escn)
2815 if (!ML_(sli_is_valid)(debug_types_escn))
2816 FIND(".zdebug_types", debug_types_escn)
2818 FIND( ".debug_abbrev", debug_abbv_escn)
2819 if (!ML_(sli_is_valid)(debug_abbv_escn))
2820 FIND(".zdebug_abbrev", debug_abbv_escn)
2822 FIND( ".debug_str", debug_str_escn)
2823 if (!ML_(sli_is_valid)(debug_str_escn))
2824 FIND(".zdebug_str", debug_str_escn)
2826 FIND( ".debug_line_str", debug_line_str_escn)
2827 if (!ML_(sli_is_valid)(debug_line_str_escn))
2828 FIND(".zdebug_str", debug_line_str_escn)
2830 FIND( ".debug_ranges", debug_ranges_escn)
2831 if (!ML_(sli_is_valid)(debug_ranges_escn))
2832 FIND(".zdebug_ranges", debug_ranges_escn)
2834 FIND( ".debug_rnglists", debug_rnglists_escn)
2835 if (!ML_(sli_is_valid)(debug_rnglists_escn))
2836 FIND(".zdebug_rnglists", debug_rnglists_escn)
2838 FIND( ".debug_loclists", debug_loclists_escn)
2839 if (!ML_(sli_is_valid)(debug_loclists_escn))
2840 FIND(".zdebug_loclists", debug_loclists_escn)
2842 FIND( ".debug_loc", debug_loc_escn)
2843 if (!ML_(sli_is_valid)(debug_loc_escn))
2844 FIND(".zdebug_loc", debug_loc_escn)
2846 FIND( ".debug_frame", debug_frame_escn)
2847 if (!ML_(sli_is_valid)(debug_frame_escn))
2848 FIND(".zdebug_frame", debug_frame_escn)
2850 FIND( ".debug", dwarf1d_escn)
2851 FIND( ".line", dwarf1l_escn)
2853 FIND( ".opd", opd_escn)
2855 FINDX( ".eh_frame", ehframe_escn[ehframe_mix],
2856 do { ehframe_mix++; vg_assert(ehframe_mix <= N_EHFRAME_SECTS);
2857 } while (0)
2859 /* Comment_on_EH_FRAME_MULTIPLE_INSTANCES: w.r.t. .eh_frame
2860 multi-instance kludgery, how are we assured that the order
2861 in which we fill in ehframe_escn[] is consistent with the
2862 order in which we previously filled in di->ehframe_avma[]
2863 and di->ehframe_size[] ? By the fact that in both cases,
2864 these arrays were filled in by iterating over the section
2865 headers top-to-bottom. So both loops (this one and the
2866 previous one) encounter the .eh_frame entries in the same
2867 order and so fill in these arrays in a consistent order.
2870 # undef FINDX
2871 # undef FIND
2872 } /* Iterate over section headers (again) */
2874 /* TOPLEVEL */
2875 /* Now, see if we can find a debuginfo object, and if so connect
2876 |dimg| to it. */
2877 vg_assert(dimg == NULL && aimg == NULL);
2879 /* Look for a build-id */
2880 HChar* buildid = find_buildid(mimg, False, False);
2882 /* Look for a debug image that matches either the build-id or
2883 the debuglink-CRC32 in the main image. If the main image
2884 doesn't contain either of those then this won't even bother
2885 to try looking. This looks in all known places, including
2886 the --extra-debuginfo-path if specified and on the
2887 --debuginfo-server if specified. */
2888 if (buildid != NULL || debuglink_escn.img != NULL) {
2889 /* Do have a debuglink section? */
2890 if (debuglink_escn.img != NULL) {
2891 UInt crc_offset
2892 = VG_ROUNDUP(ML_(img_strlen)(debuglink_escn.img,
2893 debuglink_escn.ioff)+1, 4);
2894 vg_assert(crc_offset + sizeof(UInt) <= debuglink_escn.szB);
2896 /* Extract the CRC from the debuglink section */
2897 UInt crc = ML_(img_get_UInt)(debuglink_escn.img,
2898 debuglink_escn.ioff + crc_offset);
2900 /* See if we can find a matching debug file */
2901 HChar* debuglink_str_m
2902 = ML_(img_strdup)(debuglink_escn.img,
2903 "di.redi_dlk.1", debuglink_escn.ioff);
2904 dimg = find_debug_file( di, di->fsm.filename, buildid,
2905 debuglink_str_m, crc, False );
2906 if (debuglink_str_m)
2907 ML_(dinfo_free)(debuglink_str_m);
2908 } else {
2909 /* See if we can find a matching debug file */
2910 dimg = find_debug_file( di, di->fsm.filename, buildid,
2911 NULL, 0, False );
2915 if (buildid) {
2916 ML_(dinfo_free)(buildid);
2917 buildid = NULL; /* paranoia */
2920 /* As a last-ditch measure, try looking for in the
2921 --extra-debuginfo-path and/or on the --debuginfo-server, but
2922 only in the case where --allow-mismatched-debuginfo=yes.
2923 This is dangerous in that (1) it gives no assurance that the
2924 debuginfo object matches the main one, and hence (2) we will
2925 very likely get an assertion in the code below, if indeed
2926 there is a mismatch. Hence it is disabled by default
2927 (--allow-mismatched-debuginfo=no). Nevertheless it's
2928 sometimes a useful way of getting out of a tight spot.
2930 Note that we're ignoring the name in the .gnu_debuglink
2931 section here, and just looking for a file of the same name
2932 either the extra-path or on the server. */
2933 if (dimg == NULL && VG_(clo_allow_mismatched_debuginfo)) {
2934 dimg = find_debug_file_ad_hoc( di, di->fsm.filename );
2937 /* TOPLEVEL */
2938 /* If we were successful in finding a debug image, pull various
2939 SVMA/bias/size and image addresses out of it. */
2940 if (dimg != NULL && is_elf_object_file_by_DiImage(dimg, False)) {
2942 /* Pull out and validate program header and section header info */
2943 DiOffT ehdr_dioff = 0;
2944 ElfXX_Ehdr ehdr_dimg;
2945 ML_(img_get)(&ehdr_dimg, dimg, ehdr_dioff, sizeof(ehdr_dimg));
2947 DiOffT phdr_dioff = ehdr_dimg.e_phoff;
2948 UWord phdr_dnent = ehdr_dimg.e_phnum;
2949 UWord phdr_dent_szB = ehdr_dimg.e_phentsize;
2951 DiOffT shdr_dioff = ehdr_dimg.e_shoff;
2952 UWord shdr_dnent = ehdr_dimg.e_shnum;
2953 UWord shdr_dent_szB = ehdr_dimg.e_shentsize;
2955 DiOffT shdr_strtab_dioff = DiOffT_INVALID;
2957 /* SVMAs covered by rx and rw segments and corresponding bias. */
2958 Addr rx_dsvma_limit = 0;
2959 PtrdiffT rx_dbias = 0;
2960 Addr rw_dsvma_limit = 0;
2961 PtrdiffT rw_dbias = 0;
2963 Bool need_symtab, need_dwarf2, need_dwarf1;
2965 if (phdr_dnent == 0
2966 || !ML_(img_valid)(dimg, phdr_dioff,
2967 phdr_dnent * phdr_dent_szB)) {
2968 ML_(symerr)(di, True,
2969 "Missing or invalid ELF Program Header Table"
2970 " (debuginfo file)");
2971 goto out;
2974 if (shdr_dnent == 0
2975 || !ML_(img_valid)(dimg, shdr_dioff,
2976 shdr_dnent * shdr_dent_szB)) {
2977 ML_(symerr)(di, True,
2978 "Missing or invalid ELF Section Header Table"
2979 " (debuginfo file)");
2980 goto out;
2983 /* Also find the section header's string table, and validate. */
2984 /* checked previously by is_elf_object_file: */
2985 vg_assert(ehdr_dimg.e_shstrndx != SHN_UNDEF);
2987 // shdr_dioff is the offset of the section header table
2988 // and we need the ehdr_dimg.e_shstrndx'th entry
2989 { ElfXX_Shdr a_shdr;
2990 ML_(img_get)(&a_shdr, dimg,
2991 INDEX_BIS(shdr_dioff, ehdr_dimg.e_shstrndx,
2992 shdr_dent_szB),
2993 sizeof(a_shdr));
2994 shdr_strtab_dioff = a_shdr.sh_offset;
2995 if (!ML_(img_valid)(dimg, shdr_strtab_dioff,
2996 1/*bogus, but we don't know the real size*/)) {
2997 ML_(symerr)(di, True,
2998 "Invalid ELF Section Header String Table"
2999 " (debuginfo file)");
3000 goto out;
3004 for (i = 0; i < ehdr_dimg.e_phnum; i++) {
3005 ElfXX_Phdr a_phdr;
3006 ML_(img_get)(&a_phdr, dimg, INDEX_BIS(ehdr_dimg.e_phoff,
3007 i, phdr_dent_szB),
3008 sizeof(a_phdr));
3009 if (a_phdr.p_type == PT_LOAD) {
3010 for (j = 0; j < VG_(sizeXA)(di->fsm.maps); j++) {
3011 const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, j);
3012 if ( a_phdr.p_offset >= map->foff
3013 && a_phdr.p_offset < map->foff + map->size
3014 && a_phdr.p_offset + a_phdr.p_filesz
3015 < map->foff + map->size) {
3016 if (map->rx && rx_dsvma_limit == 0) {
3017 rx_dsvma_limit = a_phdr.p_vaddr + a_phdr.p_memsz;
3018 rx_dbias = map->avma - map->foff + a_phdr.p_offset
3019 - a_phdr.p_vaddr;
3021 if (map->rw && rw_dsvma_limit == 0) {
3022 rw_dsvma_limit = a_phdr.p_vaddr + a_phdr.p_memsz;
3023 rw_dbias = map->avma - map->foff + a_phdr.p_offset
3024 - a_phdr.p_vaddr;
3026 break;
3032 need_symtab = (symtab_escn.img == NULL);
3033 need_dwarf2 = (debug_info_escn.img == NULL);
3034 need_dwarf1 = (dwarf1d_escn.img == NULL);
3036 /* Find all interesting sections in the debug image */
3037 for (i = 0; i < ehdr_dimg.e_shnum; i++) {
3039 /* Find debug svma and bias information for sections
3040 we found in the main file. */
3042 # define FIND(_sec, _seg) \
3043 do { \
3044 ElfXX_Shdr a_shdr; \
3045 ML_(img_get)(&a_shdr, dimg, \
3046 INDEX_BIS(shdr_dioff, i, shdr_dent_szB), \
3047 sizeof(a_shdr)); \
3048 if (di->_sec##_present \
3049 && 0 == ML_(img_strcmp_c)(dimg, shdr_strtab_dioff \
3050 + a_shdr.sh_name, "." #_sec)) { \
3051 vg_assert(di->_sec##_size == a_shdr.sh_size); \
3052 /* JRS 2013-Jun-01: the following assert doesn't contain */ \
3053 /* any ==s, which seems to me to be suspicious. */ \
3054 vg_assert(di->_sec##_avma + a_shdr.sh_addr + _seg##_dbias); \
3055 /* Assume we have a correct value for the main */ \
3056 /* object's bias. Use that to derive the debuginfo */ \
3057 /* object's bias, by adding the difference in SVMAs */ \
3058 /* for the corresponding sections in the two files. */ \
3059 /* That should take care of all prelinking effects. */ \
3060 di->_sec##_debug_svma = a_shdr.sh_addr; \
3061 di->_sec##_debug_bias \
3062 = di->_sec##_bias + \
3063 di->_sec##_svma - di->_sec##_debug_svma; \
3064 TRACE_SYMTAB("acquiring ." #_sec \
3065 " debug svma = %#lx .. %#lx\n", \
3066 di->_sec##_debug_svma, \
3067 di->_sec##_debug_svma + di->_sec##_size - 1); \
3068 TRACE_SYMTAB("acquiring ." #_sec " debug bias = %#lx\n", \
3069 (UWord)di->_sec##_debug_bias); \
3071 } while (0);
3073 /* SECTION SEGMENT */
3074 FIND(text, rx)
3075 FIND(data, rw)
3076 FIND(sdata, rw)
3077 FIND(rodata, rw)
3078 FIND(bss, rw)
3079 FIND(sbss, rw)
3081 # undef FIND
3083 /* Same deal as previous FIND, except only do it for those
3084 sections which we didn't find in the main file. */
3086 # define FIND(_condition, _sec_name, _sec_escn) \
3087 do { \
3088 ElfXX_Shdr a_shdr; \
3089 ML_(img_get)(&a_shdr, dimg, \
3090 INDEX_BIS(shdr_dioff, i, shdr_dent_szB), \
3091 sizeof(a_shdr)); \
3092 if (_condition \
3093 && 0 == ML_(img_strcmp_c)(dimg, shdr_strtab_dioff \
3094 + a_shdr.sh_name, _sec_name)) { \
3095 Bool nobits; \
3096 if (_sec_escn.img != NULL) { \
3097 ML_(symerr)(di, True, \
3098 " debuginfo section duplicates a" \
3099 " section in the main ELF file"); \
3100 goto out; \
3102 _sec_escn.img = dimg; \
3103 _sec_escn.ioff = (DiOffT)a_shdr.sh_offset; \
3104 _sec_escn.szB = a_shdr.sh_size; \
3105 if (!check_compression(&a_shdr, &_sec_escn)) { \
3106 ML_(symerr)(di, True, " Compression type is unsupported"); \
3107 goto out; \
3109 nobits = a_shdr.sh_type == SHT_NOBITS; \
3110 vg_assert(_sec_escn.img != NULL); \
3111 vg_assert(_sec_escn.ioff != DiOffT_INVALID); \
3112 TRACE_SYMTAB( "%-18s: dioff %llu .. %llu\n", \
3113 _sec_name, \
3114 (ULong)a_shdr.sh_offset, \
3115 ((ULong)a_shdr.sh_offset) + a_shdr.sh_size - 1); \
3116 /* SHT_NOBITS sections have zero size in the file. */ \
3117 if (!nobits && a_shdr.sh_offset \
3118 + a_shdr.sh_size > ML_(img_real_size)(_sec_escn.img)) { \
3119 ML_(symerr)(di, True, \
3120 " section beyond image end?!"); \
3121 goto out; \
3124 } while (0);
3126 /* NEEDED? NAME ElfSec */
3127 FIND( need_symtab, ".symtab", symtab_escn)
3128 FIND( need_symtab, ".strtab", strtab_escn)
3129 FIND( need_dwarf2, ".debug_line", debug_line_escn)
3130 if (!ML_(sli_is_valid)(debug_line_escn))
3131 FIND(need_dwarf2, ".zdebug_line", debug_line_escn)
3133 FIND( need_dwarf2, ".debug_info", debug_info_escn)
3134 if (!ML_(sli_is_valid)(debug_info_escn))
3135 FIND(need_dwarf2, ".zdebug_info", debug_info_escn)
3137 FIND( need_dwarf2, ".debug_types", debug_types_escn)
3138 if (!ML_(sli_is_valid)(debug_types_escn))
3139 FIND(need_dwarf2, ".zdebug_types", debug_types_escn)
3141 FIND( need_dwarf2, ".debug_abbrev", debug_abbv_escn)
3142 if (!ML_(sli_is_valid)(debug_abbv_escn))
3143 FIND(need_dwarf2, ".zdebug_abbrev", debug_abbv_escn)
3145 FIND( need_dwarf2, ".debug_str", debug_str_escn)
3146 if (!ML_(sli_is_valid)(debug_str_escn))
3147 FIND(need_dwarf2, ".zdebug_str", debug_str_escn)
3149 FIND( need_dwarf2, ".debug_line_str", debug_line_str_escn)
3150 if (!ML_(sli_is_valid)(debug_line_str_escn))
3151 FIND(need_dwarf2, ".zdebug_line_str", debug_line_str_escn)
3153 FIND( need_dwarf2, ".debug_ranges", debug_ranges_escn)
3154 if (!ML_(sli_is_valid)(debug_ranges_escn))
3155 FIND(need_dwarf2, ".zdebug_ranges", debug_ranges_escn)
3157 FIND( need_dwarf2, ".debug_rnglists", debug_rnglists_escn)
3158 if (!ML_(sli_is_valid)(debug_rnglists_escn))
3159 FIND(need_dwarf2, ".zdebug_rnglists", debug_rnglists_escn)
3161 FIND( need_dwarf2, ".debug_loclists", debug_loclists_escn)
3162 if (!ML_(sli_is_valid)(debug_loclists_escn))
3163 FIND(need_dwarf2, ".zdebug_loclists", debug_loclists_escn)
3165 FIND( need_dwarf2, ".debug_loc", debug_loc_escn)
3166 if (!ML_(sli_is_valid)(debug_loc_escn))
3167 FIND(need_dwarf2, ".zdebug_loc", debug_loc_escn)
3169 FIND( need_dwarf2, ".debug_frame", debug_frame_escn)
3170 if (!ML_(sli_is_valid)(debug_frame_escn))
3171 FIND(need_dwarf2, ".zdebug_frame", debug_frame_escn)
3173 FIND( need_dwarf2, ".gnu_debugaltlink", debugaltlink_escn)
3175 FIND( need_dwarf1, ".debug", dwarf1d_escn)
3176 FIND( need_dwarf1, ".line", dwarf1l_escn)
3178 # undef FIND
3179 } /* Find all interesting sections */
3180 } /* do we have a debug image? */
3182 /* TOPLEVEL */
3183 /* Look for alternate debug image, and if found, connect |aimg|
3184 to it. */
3185 vg_assert(aimg == NULL);
3187 if (debugaltlink_escn.img != NULL) {
3188 HChar* altfile_str_m
3189 = ML_(img_strdup)(debugaltlink_escn.img,
3190 "di.fbi.3", debugaltlink_escn.ioff);
3191 UInt buildid_offset = ML_(img_strlen)(debugaltlink_escn.img,
3192 debugaltlink_escn.ioff)+1;
3194 vg_assert(buildid_offset < debugaltlink_escn.szB);
3196 HChar *altbuildid
3197 = ML_(dinfo_zalloc)("di.fbi.4",
3198 (debugaltlink_escn.szB - buildid_offset)
3199 * 2 + 1);
3201 /* The altfile might be relative to the debug file or main file.
3202 Make sure that we got the real file, not a symlink. */
3203 HChar *dbgname = di->fsm.dbgname ? di->fsm.dbgname : di->fsm.filename;
3204 HChar* rdbgname = readlink_path (dbgname);
3205 if (rdbgname == NULL)
3206 rdbgname = ML_(dinfo_strdup)("rdbgname", dbgname);
3208 for (j = 0; j < debugaltlink_escn.szB - buildid_offset; j++)
3209 VG_(sprintf)(
3210 altbuildid + 2 * j, "%02x",
3211 (UInt)ML_(img_get_UChar)(debugaltlink_escn.img,
3212 debugaltlink_escn.ioff
3213 + buildid_offset + j));
3215 /* See if we can find a matching debug file */
3216 aimg = find_debug_file( di, rdbgname, altbuildid,
3217 altfile_str_m, 0, True );
3219 ML_(dinfo_free)(rdbgname);
3221 if (altfile_str_m)
3222 ML_(dinfo_free)(altfile_str_m);
3223 ML_(dinfo_free)(altbuildid);
3226 /* TOPLEVEL */
3227 /* If we were successful in finding alternate debug image, pull various
3228 size and image addresses out of it. */
3229 if (aimg != NULL && is_elf_object_file_by_DiImage(aimg, True)) {
3231 /* Pull out and validate program header and section header info */
3232 DiOffT ehdr_aioff = 0;
3233 ElfXX_Ehdr ehdr_aimg;
3234 ML_(img_get)(&ehdr_aimg, aimg, ehdr_aioff, sizeof(ehdr_aimg));
3236 DiOffT shdr_aioff = ehdr_aimg.e_shoff;
3237 UWord shdr_anent = ehdr_aimg.e_shnum;
3238 UWord shdr_aent_szB = ehdr_aimg.e_shentsize;
3240 DiOffT shdr_strtab_aioff = DiOffT_INVALID;
3242 if (shdr_anent == 0
3243 || !ML_(img_valid)(aimg, shdr_aioff,
3244 shdr_anent * shdr_aent_szB)) {
3245 ML_(symerr)(di, True,
3246 "Missing or invalid ELF Section Header Table"
3247 " (alternate debuginfo file)");
3248 goto out;
3251 /* Also find the section header's string table, and validate. */
3252 /* checked previously by is_elf_object_file: */
3253 vg_assert(ehdr_aimg.e_shstrndx != SHN_UNDEF);
3255 // shdr_aioff is the offset of the section header table
3256 // and we need the ehdr_aimg.e_shstrndx'th entry
3257 { ElfXX_Shdr a_shdr;
3258 ML_(img_get)(&a_shdr, aimg,
3259 INDEX_BIS(shdr_aioff, ehdr_aimg.e_shstrndx,
3260 shdr_aent_szB),
3261 sizeof(a_shdr));
3262 shdr_strtab_aioff = a_shdr.sh_offset;
3263 if (!ML_(img_valid)(aimg, shdr_strtab_aioff,
3264 1/*bogus, but we don't know the real size*/)) {
3265 ML_(symerr)(di, True,
3266 "Invalid ELF Section Header String Table"
3267 " (alternate debuginfo file)");
3268 goto out;
3272 /* Find all interesting sections */
3273 for (i = 0; i < ehdr_aimg.e_shnum; i++) {
3275 # define FIND(_sec_name, _sec_escn) \
3276 do { \
3277 ElfXX_Shdr a_shdr; \
3278 ML_(img_get)(&a_shdr, aimg, \
3279 INDEX_BIS(shdr_aioff, i, shdr_aent_szB), \
3280 sizeof(a_shdr)); \
3281 if (0 == ML_(img_strcmp_c)(aimg, shdr_strtab_aioff \
3282 + a_shdr.sh_name, _sec_name)) { \
3283 if (_sec_escn.img != NULL) { \
3284 ML_(symerr)(di, True, \
3285 " alternate debuginfo section duplicates a" \
3286 " section in the main ELF file"); \
3287 goto out; \
3289 _sec_escn.img = aimg; \
3290 _sec_escn.ioff = (DiOffT)a_shdr.sh_offset; \
3291 _sec_escn.szB = a_shdr.sh_size; \
3292 if (!check_compression(&a_shdr, &_sec_escn)) { \
3293 ML_(symerr)(di, True, " Compression type is " \
3294 "unsupported"); \
3295 goto out; \
3297 vg_assert(_sec_escn.img != NULL); \
3298 vg_assert(_sec_escn.ioff != DiOffT_INVALID); \
3299 TRACE_SYMTAB( "%-18s: aioff %llu .. %llu\n", \
3300 _sec_name, \
3301 (ULong)a_shdr.sh_offset, \
3302 ((ULong)a_shdr.sh_offset) + a_shdr.sh_size - 1); \
3304 } while (0);
3306 /* NAME ElfSec */
3307 FIND(".debug_line", debug_line_alt_escn)
3308 if (!ML_(sli_is_valid)(debug_line_alt_escn))
3309 FIND(".zdebug_line", debug_line_alt_escn)
3311 FIND(".debug_info", debug_info_alt_escn)
3312 if (!ML_(sli_is_valid)(debug_info_alt_escn))
3313 FIND(".zdebug_info", debug_info_alt_escn)
3315 FIND(".debug_abbrev", debug_abbv_alt_escn)
3316 if (!ML_(sli_is_valid)(debug_abbv_alt_escn))
3317 FIND(".zdebug_abbrev", debug_abbv_alt_escn)
3319 FIND(".debug_str", debug_str_alt_escn)
3320 if (!ML_(sli_is_valid)(debug_str_alt_escn))
3321 FIND(".zdebug_str", debug_str_alt_escn)
3323 # undef FIND
3324 } /* Find all interesting sections */
3325 } /* do we have a debug image? */
3328 /* TOPLEVEL */
3329 /* Check some sizes */
3330 vg_assert((dynsym_escn.szB % sizeof(ElfXX_Sym)) == 0);
3331 vg_assert((symtab_escn.szB % sizeof(ElfXX_Sym)) == 0);
3332 # if defined(VGO_solaris)
3333 vg_assert((ldynsym_escn.szB % sizeof(ElfXX_Sym)) == 0);
3334 # endif
3336 /* TOPLEVEL */
3337 /* Read symbols */
3339 void (*read_elf_symtab)(struct _DebugInfo*, const HChar*,
3340 DiSlice*, DiSlice*, DiSlice*, Bool);
3341 Bool symtab_in_debug;
3342 # if defined(VGP_ppc64be_linux)
3343 read_elf_symtab = read_elf_symtab__ppc64be_linux;
3344 # else
3345 read_elf_symtab = read_elf_symtab__normal;
3346 # endif
3347 symtab_in_debug = symtab_escn.img == dimg;
3348 read_elf_symtab(di, "symbol table",
3349 &symtab_escn, &strtab_escn, &opd_escn,
3350 symtab_in_debug);
3351 read_elf_symtab(di, "dynamic symbol table",
3352 &dynsym_escn, &dynstr_escn, &opd_escn,
3353 False);
3354 # if defined(VGO_solaris)
3355 read_elf_symtab(di, "local dynamic symbol table",
3356 &ldynsym_escn, &dynstr_escn, &opd_escn,
3357 False);
3358 # endif
3361 /* TOPLEVEL */
3362 /* Read .eh_frame and .debug_frame (call-frame-info) if any. Do
3363 the .eh_frame section(s) first. */
3364 vg_assert(di->n_ehframe >= 0 && di->n_ehframe <= N_EHFRAME_SECTS);
3365 for (i = 0; i < di->n_ehframe; i++) {
3366 /* see Comment_on_EH_FRAME_MULTIPLE_INSTANCES above for why
3367 this next assertion should hold. */
3368 vg_assert(ML_(sli_is_valid)(ehframe_escn[i]));
3369 vg_assert(ehframe_escn[i].szB == di->ehframe_size[i]);
3370 ML_(read_callframe_info_dwarf3)( di,
3371 ehframe_escn[i],
3372 di->ehframe_avma[i],
3373 True/*is_ehframe*/ );
3375 if (ML_(sli_is_valid)(debug_frame_escn)) {
3376 ML_(read_callframe_info_dwarf3)( di,
3377 debug_frame_escn,
3378 0/*assume zero avma*/,
3379 False/*!is_ehframe*/ );
3382 /* TOPLEVEL */
3383 /* jrs 2006-01-01: icc-8.1 has been observed to generate
3384 binaries without debug_str sections. Don't preclude
3385 debuginfo reading for that reason, but, in
3386 read_unitinfo_dwarf2, do check that debugstr is non-NULL
3387 before using it. */
3388 if (ML_(sli_is_valid)(debug_info_escn)
3389 && ML_(sli_is_valid)(debug_abbv_escn)
3390 && ML_(sli_is_valid)(debug_line_escn)) {
3391 /* The old reader: line numbers and unwind info only */
3392 ML_(read_debuginfo_dwarf3) ( di,
3393 debug_info_escn,
3394 debug_types_escn,
3395 debug_abbv_escn,
3396 debug_line_escn,
3397 debug_str_escn,
3398 debug_str_alt_escn,
3399 debug_line_str_escn);
3400 /* The new reader: read the DIEs in .debug_info to acquire
3401 information on variable types and locations or inline info.
3402 But only if the tool asks for it, or the user requests it on
3403 the command line. */
3404 if (VG_(clo_read_var_info) /* the user or tool asked for it */
3405 || VG_(clo_read_inline_info)) {
3406 ML_(new_dwarf3_reader)(
3407 di, debug_info_escn, debug_types_escn,
3408 debug_abbv_escn, debug_line_escn,
3409 debug_str_escn, debug_ranges_escn,
3410 debug_rnglists_escn, debug_loclists_escn,
3411 debug_loc_escn, debug_info_alt_escn,
3412 debug_abbv_alt_escn, debug_line_alt_escn,
3413 debug_str_alt_escn, debug_line_str_escn
3418 /* TOPLEVEL */
3419 // JRS 31 July 2014: dwarf-1 reading is currently broken and
3420 // therefore deactivated.
3421 //if (dwarf1d_img && dwarf1l_img) {
3422 // ML_(read_debuginfo_dwarf1) ( di, dwarf1d_img, dwarf1d_sz,
3423 // dwarf1l_img, dwarf1l_sz );
3426 # if defined(VGA_arm)
3427 /* TOPLEVEL */
3428 /* ARM32 only: read .exidx/.extab if present. Note we are
3429 reading these directly out of the mapped in (running) image.
3430 Also, read these only if no CFI based unwind info was
3431 acquired for this file.
3433 An .exidx section is always required, but the .extab section
3434 can be optionally omitted, provided that .exidx does not
3435 refer to it. If the .exidx is erroneous and does refer to
3436 .extab even though .extab is missing, the range checks done
3437 by GET_EX_U32 in ExtabEntryExtract in readexidx.c should
3438 prevent any invalid memory accesses, and cause the .extab to
3439 be rejected as invalid.
3441 FIXME:
3442 * check with m_aspacemgr that the entire [exidx_avma, +exidx_size)
3443 and [extab_avma, +extab_size) areas are readable, since we're
3444 reading this stuff out of the running image (not from a file/socket)
3445 and we don't want to segfault.
3446 * DebugInfo::exidx_bias and use text_bias instead.
3447 I think it's always the same.
3448 * remove DebugInfo::{extab_bias, exidx_svma, extab_svma} since
3449 they are never used.
3451 if (di->exidx_present
3452 && di->cfsi_used == 0
3453 && di->text_present && di->text_size > 0) {
3454 Addr text_last_svma = di->text_svma + di->text_size - 1;
3455 ML_(read_exidx)( di, (UChar*)di->exidx_avma, di->exidx_size,
3456 (UChar*)di->extab_avma, di->extab_size,
3457 text_last_svma,
3458 di->exidx_bias );
3460 # endif /* defined(VGA_arm) */
3462 } /* "Find interesting sections, read the symbol table(s), read any debug
3463 information" (a local scope) */
3465 /* TOPLEVEL */
3466 res = True;
3468 /* If reading Dwarf3 variable type/location info, print a line
3469 showing the number of variables read for each object.
3470 (Currently disabled -- is a sanity-check mechanism for
3471 exp-sgcheck.) */
3472 if (0 && VG_(clo_read_var_info)) {
3473 UWord nVars = 0;
3474 if (di->varinfo) {
3475 for (j = 0; j < VG_(sizeXA)(di->varinfo); j++) {
3476 OSet* /* of DiAddrRange */ scope
3477 = *(OSet**)VG_(indexXA)(di->varinfo, j);
3478 vg_assert(scope);
3479 VG_(OSetGen_ResetIter)( scope );
3480 while (True) {
3481 DiAddrRange* range = VG_(OSetGen_Next)( scope );
3482 if (!range) break;
3483 vg_assert(range->vars);
3484 Word w = VG_(sizeXA)(range->vars);
3485 vg_assert(w >= 0);
3486 if (0) VG_(printf)("range %#lx %#lx %ld\n",
3487 range->aMin, range->aMax, w);
3488 nVars += (UWord)w;
3492 VG_(umsg)("VARINFO: %7lu vars %7lu text_size %s\n",
3493 nVars, di->text_size, di->fsm.filename);
3495 /* TOPLEVEL */
3497 out:
3499 /* Last, but not least, detach from the image(s). */
3500 if (mimg) ML_(img_done)(mimg);
3501 if (dimg) ML_(img_done)(dimg);
3502 if (aimg) ML_(img_done)(aimg);
3504 if (svma_ranges) VG_(deleteXA)(svma_ranges);
3506 return res;
3507 } /* out: */
3509 /* NOTREACHED */
3512 #endif // defined(VGO_linux) || defined(VGO_solaris)
3514 /*--------------------------------------------------------------------*/
3515 /*--- end ---*/
3516 /*--------------------------------------------------------------------*/