Fix DRD and Helgrind on Solaris.
[valgrind.git] / coregrind / m_debuginfo / readelf.c
blob56e7d4b6f08f539f740eafd8848cf6c423e86ed8
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) || defined(VGO_freebsd)
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 "pub_core_libcproc.h"
49 #include "priv_misc.h" /* dinfo_zalloc/free/strdup */
50 #include "priv_image.h"
51 #include "priv_d3basics.h"
52 #include "priv_tytypes.h"
53 #include "priv_storage.h"
54 #include "priv_readelf.h" /* self */
55 #include "priv_readdwarf.h" /* 'cos ELF contains DWARF */
56 #include "priv_readdwarf3.h"
57 #include "priv_readexidx.h"
58 #include "config.h"
60 /* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
61 #include <elf.h>
62 #if defined(VGO_solaris)
63 #include <sys/link.h> /* ElfXX_Dyn, DT_* */
64 #endif
65 /* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
67 #if !defined(HAVE_ELF32_CHDR)
68 typedef struct {
69 Elf32_Word ch_type;
70 Elf32_Word ch_size;
71 Elf32_Word ch_addralign;
72 } Elf32_Chdr;
73 #endif
75 #if !defined(HAVE_ELF64_CHDR)
76 typedef struct {
77 Elf64_Word ch_type;
78 Elf64_Word ch_reserved;
79 Elf64_Xword ch_size;
80 Elf64_Xword ch_addralign;
81 } Elf64_Chdr;
82 #endif
84 #if !defined(SHF_COMPRESSED)
85 #define SHF_COMPRESSED (1 << 11)
86 #endif
88 #if !defined(ELFCOMPRESS_ZLIB)
89 #define ELFCOMPRESS_ZLIB 1
90 #endif
92 #define SIZE_OF_ZLIB_HEADER 12
94 /*------------------------------------------------------------*/
95 /*--- 32/64-bit parameterisation ---*/
96 /*------------------------------------------------------------*/
98 /* For all the ELF macros and types which specify '32' or '64',
99 select the correct variant for this platform and give it
100 an 'XX' name. Then use the 'XX' variant consistently in
101 the rest of this file.
103 #if VG_WORDSIZE == 4
104 # define ElfXX_Ehdr Elf32_Ehdr
105 # define ElfXX_Shdr Elf32_Shdr
106 # define ElfXX_Phdr Elf32_Phdr
107 # define ElfXX_Nhdr Elf32_Nhdr
108 # define ElfXX_Sym Elf32_Sym
109 # define ElfXX_Off Elf32_Off
110 # define ElfXX_Word Elf32_Word
111 # define ElfXX_Addr Elf32_Addr
112 # define ElfXX_Dyn Elf32_Dyn
113 # define ELFXX_ST_BIND ELF32_ST_BIND
114 # define ELFXX_ST_TYPE ELF32_ST_TYPE
115 # define ElfXX_Chdr Elf32_Chdr
117 #elif VG_WORDSIZE == 8
118 # define ElfXX_Ehdr Elf64_Ehdr
119 # define ElfXX_Shdr Elf64_Shdr
120 # define ElfXX_Phdr Elf64_Phdr
121 # define ElfXX_Nhdr Elf64_Nhdr
122 # define ElfXX_Sym Elf64_Sym
123 # define ElfXX_Off Elf64_Off
124 # define ElfXX_Word Elf64_Word
125 # define ElfXX_Addr Elf64_Addr
126 # define ElfXX_Dyn Elf64_Dyn
127 # define ELFXX_ST_BIND ELF64_ST_BIND
128 # define ELFXX_ST_TYPE ELF64_ST_TYPE
129 # define ElfXX_Chdr Elf64_Chdr
131 #else
132 # error "VG_WORDSIZE should be 4 or 8"
133 #endif
136 /*------------------------------------------------------------*/
137 /*--- ---*/
138 /*--- Read symbol table and line info from ELF files. ---*/
139 /*--- ---*/
140 /*------------------------------------------------------------*/
142 /* readelf.c parses ELF files and acquires symbol table info from
143 them. It calls onwards to readdwarf.c to read DWARF2/3 line number
144 and call frame info found. */
146 /* Identify an ELF object file by peering at the first few bytes of
147 it. */
149 Bool ML_(is_elf_object_file)( const void* image, SizeT n_image, Bool rel_ok )
151 const ElfXX_Ehdr* ehdr = image;
152 Int ok = 1;
154 if (n_image < sizeof(ElfXX_Ehdr))
155 return False;
157 ok &= (ehdr->e_ident[EI_MAG0] == 0x7F
158 && ehdr->e_ident[EI_MAG1] == 'E'
159 && ehdr->e_ident[EI_MAG2] == 'L'
160 && ehdr->e_ident[EI_MAG3] == 'F');
161 ok &= (ehdr->e_ident[EI_CLASS] == VG_ELF_CLASS
162 && ehdr->e_ident[EI_DATA] == VG_ELF_DATA2XXX
163 && ehdr->e_ident[EI_VERSION] == EV_CURRENT);
164 ok &= (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN
165 || (rel_ok && ehdr->e_type == ET_REL));
166 ok &= (ehdr->e_machine == VG_ELF_MACHINE);
167 ok &= (ehdr->e_version == EV_CURRENT);
168 ok &= (ehdr->e_shstrndx != SHN_UNDEF);
169 ok &= (ehdr->e_shoff != 0 && ehdr->e_shnum != 0);
170 ok &= ((ehdr->e_phoff != 0 && ehdr->e_phnum != 0)
171 || ehdr->e_type == ET_REL);
173 return ok ? True : False;
177 /* The same thing, but operating on a DiImage instead. */
179 static Bool is_elf_object_file_by_DiImage( DiImage* img, Bool rel_ok )
181 /* Be sure this doesn't make the frame too big. */
182 vg_assert(sizeof(ElfXX_Ehdr) <= 512);
184 ElfXX_Ehdr ehdr;
185 if (!ML_(img_valid)(img, 0, sizeof(ehdr)))
186 return False;
188 ML_(img_get)(&ehdr, img, 0, sizeof(ehdr));
189 return ML_(is_elf_object_file)( &ehdr, sizeof(ehdr), rel_ok );
193 /* Show a raw ELF symbol, given its in-image address and name. */
195 static
196 void show_raw_elf_symbol ( DiImage* strtab_img,
197 Int i,
198 const ElfXX_Sym* sym,
199 DiOffT sym_name_ioff, Addr sym_svma,
200 Bool ppc64_linux_format )
202 const HChar* space = ppc64_linux_format ? " " : "";
203 VG_(printf)("raw symbol [%4d]: ", i);
204 switch (ELFXX_ST_BIND(sym->st_info)) {
205 case STB_LOCAL: VG_(printf)("LOC "); break;
206 case STB_GLOBAL: VG_(printf)("GLO "); break;
207 case STB_WEAK: VG_(printf)("WEA "); break;
208 case STB_LOPROC: VG_(printf)("lop "); break;
209 case STB_HIPROC: VG_(printf)("hip "); break;
210 default: VG_(printf)("??? "); break;
212 switch (ELFXX_ST_TYPE(sym->st_info)) {
213 case STT_NOTYPE: VG_(printf)("NOT "); break;
214 case STT_OBJECT: VG_(printf)("OBJ "); break;
215 case STT_FUNC: VG_(printf)("FUN "); break;
216 case STT_SECTION: VG_(printf)("SEC "); break;
217 case STT_FILE: VG_(printf)("FIL "); break;
218 case STT_LOPROC: VG_(printf)("lop "); break;
219 case STT_HIPROC: VG_(printf)("hip "); break;
220 default: VG_(printf)("??? "); break;
222 HChar* sym_name = NULL;
223 if (sym->st_name)
224 sym_name = ML_(img_strdup)(strtab_img, "di.sres.1", sym_name_ioff);
225 VG_(printf)(": svma %#010lx, %ssz %4llu %s\n",
226 sym_svma, space, (ULong)(sym->st_size + 0UL),
227 (sym_name ? sym_name : "NONAME") );
228 if (sym_name)
229 ML_(dinfo_free)(sym_name);
233 /* Decide whether SYM is something we should collect, and if so, copy
234 relevant info to the _OUT arguments. For {x86,amd64,ppc32}-linux
235 this is straightforward - the name, address, size are copied out
236 unchanged.
238 There is a bit of a kludge re data symbols (see KLUDGED BSS CHECK
239 below): we assume that the .bss is mapped immediately after .data,
240 and so accept any data symbol which exists in the range [start of
241 .data, size of .data + size of .bss). I don't know if this is
242 really correct/justifiable, or not.
244 For ppc64be-linux it's more complex. If the symbol is seen to be in
245 the .opd section, it is taken to be a function descriptor, and so
246 a dereference is attempted, in order to get hold of the real entry
247 point address. Also as part of the dereference, there is an attempt
248 to calculate the TOC pointer (R2 value) associated with the symbol.
250 To support the ppc64be-linux pre-"dotless" ABI (prior to gcc 4.0.0),
251 if the symbol is seen to be outside the .opd section and its name
252 starts with a dot, an .opd deference is not attempted, and no TOC
253 pointer is calculated, but the leading dot is removed from the
254 name.
256 As a result, on ppc64be-linux, the caller of this function may have
257 to piece together the real size, address, name of the symbol from
258 multiple calls to this function. Ugly and confusing.
260 static
261 Bool get_elf_symbol_info (
262 /* INPUTS */
263 struct _DebugInfo* di, /* containing DebugInfo */
264 const ElfXX_Sym* sym, /* ELF symbol */
265 DiOffT sym_name_ioff, /* name, may be absent (DiOffT_INVALID) */
266 const DiSlice* escn_strtab, /* holds the name */
267 Addr sym_svma, /* address as stated in the object file */
268 Bool symtab_in_debug, /* symbol table is in the debug file */
269 const DiSlice* escn_opd, /* the .opd (ppc64be-linux only) */
270 PtrdiffT opd_bias, /* for biasing AVMAs found in .opd */
271 /* OUTPUTS */
272 DiOffT* sym_name_out_ioff, /* name (in strtab) we should record */
273 SymAVMAs* sym_avmas_out, /* sym avmas we should record */
274 Int* sym_size_out, /* symbol size */
275 Bool* from_opd_out, /* ppc64be-linux only: did we deref an
276 .opd entry? */
277 Bool* is_text_out, /* is this a text symbol? */
278 Bool* is_ifunc_out, /* is this a STT_GNU_IFUNC function ?*/
279 Bool* is_global_out /* is this a global symbol ?*/
282 Bool plausible;
283 # if defined(VGP_ppc64be_linux)
284 Bool is_in_opd;
285 # endif
286 Bool in_text, in_data, in_sdata, in_rodata, in_bss, in_sbss;
287 Addr text_svma, data_svma, sdata_svma, rodata_svma, bss_svma, sbss_svma;
288 PtrdiffT text_bias, data_bias, sdata_bias, rodata_bias, bss_bias, sbss_bias;
289 # if defined(VGPV_arm_linux_android) \
290 || defined(VGPV_x86_linux_android) \
291 || defined(VGPV_mips32_linux_android) \
292 || defined(VGPV_arm64_linux_android)
293 Addr available_size = 0;
294 #define COMPUTE_AVAILABLE_SIZE(segsvma, segsize) \
295 available_size = segsvma + segsize - sym_svma
296 #else
297 #define COMPUTE_AVAILABLE_SIZE(segsvma, segsize)
298 #endif
300 /* Set defaults */
301 *sym_name_out_ioff = sym_name_ioff;
302 (*sym_avmas_out).main = sym_svma; /* we will bias this shortly */
303 *is_text_out = True;
304 SET_TOCPTR_AVMA(*sym_avmas_out, 0); /* default to unknown/inapplicable */
305 SET_LOCAL_EP_AVMA(*sym_avmas_out, 0); /* default to unknown/inapplicable */
306 *from_opd_out = False;
307 *is_ifunc_out = False;
308 *is_global_out = False;
310 /* Get the symbol size, but restrict it to fit in a signed 32 bit
311 int. Also, deal with the stupid case of negative size by making
312 the size be 1. Note that sym->st_size has type UWord,
313 effectively. */
314 { Word size_tmp = (Word)sym->st_size;
315 Word max_Int = (1LL << 31) - 1;
316 if (size_tmp < 0) size_tmp = 1;
317 if (size_tmp > max_Int) size_tmp = max_Int;
318 *sym_size_out = (Int)size_tmp;
320 /* After this point refer only to *sym_size_out and not to
321 sym->st_size. */
323 /* Figure out if we're interested in the symbol. Firstly, is it of
324 the right flavour? */
325 plausible
326 = (ELFXX_ST_BIND(sym->st_info) == STB_GLOBAL
327 || ELFXX_ST_BIND(sym->st_info) == STB_LOCAL
328 || ELFXX_ST_BIND(sym->st_info) == STB_WEAK
331 (ELFXX_ST_TYPE(sym->st_info) == STT_FUNC
332 || ELFXX_ST_TYPE(sym->st_info) == STT_OBJECT
333 # ifdef STT_GNU_IFUNC
334 || ELFXX_ST_TYPE(sym->st_info) == STT_GNU_IFUNC
335 # endif
338 /* Work out the svma and bias for each section as it will appear in
339 addresses in the symbol table. */
340 if (symtab_in_debug) {
341 text_svma = di->text_debug_svma;
342 text_bias = di->text_debug_bias;
343 data_svma = di->data_debug_svma;
344 data_bias = di->data_debug_bias;
345 sdata_svma = di->sdata_debug_svma;
346 sdata_bias = di->sdata_debug_bias;
347 rodata_svma = di->rodata_debug_svma;
348 rodata_bias = di->rodata_debug_bias;
349 bss_svma = di->bss_debug_svma;
350 bss_bias = di->bss_debug_bias;
351 sbss_svma = di->sbss_debug_svma;
352 sbss_bias = di->sbss_debug_bias;
353 } else {
354 text_svma = di->text_svma;
355 text_bias = di->text_bias;
356 data_svma = di->data_svma;
357 data_bias = di->data_bias;
358 sdata_svma = di->sdata_svma;
359 sdata_bias = di->sdata_bias;
360 rodata_svma = di->rodata_svma;
361 rodata_bias = di->rodata_bias;
362 bss_svma = di->bss_svma;
363 bss_bias = di->bss_bias;
364 sbss_svma = di->sbss_svma;
365 sbss_bias = di->sbss_bias;
368 /* Now bias (*sym_avmas_out).main accordingly by figuring out exactly which
369 section the symbol is from and bias accordingly. Screws up if
370 the previously deduced section svma address ranges are wrong. */
371 if (di->text_present
372 && di->text_size > 0
373 && sym_svma >= text_svma
374 && sym_svma < text_svma + di->text_size) {
375 *is_text_out = True;
376 (*sym_avmas_out).main += text_bias;
377 COMPUTE_AVAILABLE_SIZE(text_svma, di->text_size);
378 } else
379 if (di->data_present
380 && di->data_size > 0
381 && sym_svma >= data_svma
382 && sym_svma < data_svma + di->data_size) {
383 *is_text_out = False;
384 (*sym_avmas_out).main += data_bias;
385 COMPUTE_AVAILABLE_SIZE(data_svma, di->data_size);
386 } else
387 if (di->sdata_present
388 && di->sdata_size > 0
389 && sym_svma >= sdata_svma
390 && sym_svma < sdata_svma + di->sdata_size) {
391 *is_text_out = False;
392 (*sym_avmas_out).main += sdata_bias;
393 COMPUTE_AVAILABLE_SIZE(sdata_svma, di->sdata_size);
394 } else
395 if (di->rodata_present
396 && di->rodata_size > 0
397 && sym_svma >= rodata_svma
398 && sym_svma < rodata_svma + di->rodata_size) {
399 *is_text_out = False;
400 (*sym_avmas_out).main += rodata_bias;
401 COMPUTE_AVAILABLE_SIZE(rodata_svma, di->rodata_size);
402 } else
403 if (di->bss_present
404 && di->bss_size > 0
405 && sym_svma >= bss_svma
406 && sym_svma < bss_svma + di->bss_size) {
407 *is_text_out = False;
408 (*sym_avmas_out).main += bss_bias;
409 COMPUTE_AVAILABLE_SIZE(bss_svma, di->bss_size);
410 } else
411 if (di->sbss_present
412 && di->sbss_size > 0
413 && sym_svma >= sbss_svma
414 && sym_svma < sbss_svma + di->sbss_size) {
415 *is_text_out = False;
416 (*sym_avmas_out).main += sbss_bias;
417 COMPUTE_AVAILABLE_SIZE(sbss_svma, di->sbss_size);
418 } else {
419 /* Assume it's in .text. Is this a good idea? */
420 *is_text_out = True;
421 (*sym_avmas_out).main += text_bias;
424 # ifdef STT_GNU_IFUNC
425 /* Check for indirect functions. */
426 if (*is_text_out
427 && ELFXX_ST_TYPE(sym->st_info) == STT_GNU_IFUNC) {
428 *is_ifunc_out = True;
430 # endif
432 if (ELFXX_ST_BIND(sym->st_info) == STB_GLOBAL) {
433 *is_global_out = True;
436 # if defined(VGP_ppc64be_linux)
437 /* Allow STT_NOTYPE in the very special case where we're running on
438 ppc64be-linux and the symbol is one which the .opd-chasing hack
439 below will chase. */
440 if (!plausible
441 && *is_text_out
442 && ELFXX_ST_TYPE(sym->st_info) == STT_NOTYPE
443 && *sym_size_out > 0
444 && di->opd_present
445 && di->opd_size > 0
446 && (*sym_avmas_out).main >= di->opd_avma
447 && (*sym_avmas_out).main < di->opd_avma + di->opd_size)
448 plausible = True;
449 # endif
451 if (!plausible)
452 return False;
454 /* Ignore if nameless. */
455 if (sym_name_ioff == DiOffT_INVALID
456 || /* VG_(strlen)(sym_name) == 0 */
457 /* equivalent but cheaper ... */
458 ML_(img_get_UChar)(escn_strtab->img, sym_name_ioff) == '\0') {
459 if (TRACE_SYMTAB_ENABLED) {
460 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
461 "di.gesi.1", sym_name_ioff);
462 TRACE_SYMTAB(" ignore -- nameless: %s\n", sym_name);
463 if (sym_name) ML_(dinfo_free)(sym_name);
465 return False;
468 /* Ignore if zero-sized. Except on Android:
470 On Android 2.3.5, some of the symbols that Memcheck needs to
471 intercept (for noise reduction purposes) have zero size, due to
472 lack of .size directives in handwritten assembly sources. So we
473 can't reject them out of hand -- instead give them a bogusly
474 large size and let canonicaliseSymtab trim them so they don't
475 overlap any following symbols. At least the following symbols
476 are known to be affected:
478 in /system/lib/libc.so: strlen strcmp strcpy memcmp memcpy
479 in /system/bin/linker: __dl_strcmp __dl_strlen
481 if (*sym_size_out == 0) {
482 # if defined(VGPV_arm_linux_android) \
483 || defined(VGPV_x86_linux_android) \
484 || defined(VGPV_mips32_linux_android) \
485 || defined(VGPV_arm64_linux_android)
486 *sym_size_out = available_size ? available_size : 2048;
487 # else
488 if (TRACE_SYMTAB_ENABLED) {
489 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
490 "di.gesi.2", sym_name_ioff);
491 TRACE_SYMTAB(" ignore -- size=0: %s\n", sym_name);
492 if (sym_name) ML_(dinfo_free)(sym_name);
494 return False;
495 # endif
498 /* This seems to significantly reduce the number of junk
499 symbols, and particularly reduces the number of
500 overlapping address ranges. Don't ask me why ... */
501 if ((Int)sym->st_value == 0) {
502 if (TRACE_SYMTAB_ENABLED) {
503 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
504 "di.gesi.3", sym_name_ioff);
505 TRACE_SYMTAB( " ignore -- valu=0: %s\n", sym_name);
506 if (sym_name) ML_(dinfo_free)(sym_name);
508 return False;
511 /* If it's apparently in a GOT or PLT, it's really a reference to a
512 symbol defined elsewhere, so ignore it. */
513 if (di->got_present
514 && di->got_size > 0
515 && (*sym_avmas_out).main >= di->got_avma
516 && (*sym_avmas_out).main < di->got_avma + di->got_size) {
517 if (TRACE_SYMTAB_ENABLED) {
518 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
519 "di.gesi.4", sym_name_ioff);
520 TRACE_SYMTAB(" ignore -- in GOT: %s\n", sym_name);
521 if (sym_name) ML_(dinfo_free)(sym_name);
523 return False;
525 if (di->plt_present
526 && di->plt_size > 0
527 && (*sym_avmas_out).main >= di->plt_avma
528 && (*sym_avmas_out).main < di->plt_avma + di->plt_size) {
529 if (TRACE_SYMTAB_ENABLED) {
530 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
531 "di.gesi.5", sym_name_ioff);
532 TRACE_SYMTAB(" ignore -- in PLT: %s\n", sym_name);
533 if (sym_name) ML_(dinfo_free)(sym_name);
535 return False;
538 /* ppc64be-linux nasty hack: if the symbol is in an .opd section,
539 then really what we have is the address of a function
540 descriptor. So use the first word of that as the function's
541 text.
543 See thread starting at
544 http://gcc.gnu.org/ml/gcc-patches/2004-08/msg00557.html
546 # if defined(VGP_ppc64be_linux)
547 /* Host and guest may have different Endianness, used by BE only */
548 is_in_opd = False;
549 # endif
551 if (di->opd_present
552 && di->opd_size > 0
553 && (*sym_avmas_out).main >= di->opd_avma
554 && (*sym_avmas_out).main < di->opd_avma + di->opd_size) {
555 # if !defined(VGP_ppc64be_linux)
556 if (TRACE_SYMTAB_ENABLED) {
557 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
558 "di.gesi.6", sym_name_ioff);
559 TRACE_SYMTAB(" ignore -- in OPD: %s\n", sym_name);
560 if (sym_name) ML_(dinfo_free)(sym_name);
562 return False;
563 # else
564 Int offset_in_opd;
565 Bool details = 1||False;
567 if (details)
568 TRACE_SYMTAB("opdXXX: opd_bias %p, sym_svma_out %p\n",
569 (void*)(opd_bias), (void*)(*sym_avmas_out).main);
571 if (!VG_IS_8_ALIGNED((*sym_avmas_out).main)) {
572 if (TRACE_SYMTAB_ENABLED) {
573 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
574 "di.gesi.6a", sym_name_ioff);
575 TRACE_SYMTAB(" ignore -- not 8-aligned: %s\n", sym_name);
576 if (sym_name) ML_(dinfo_free)(sym_name);
578 return False;
581 /* (*sym_avmas_out).main is a avma pointing into the .opd section. We
582 know the vma of the opd section start, so we can figure out
583 how far into the opd section this is. */
585 offset_in_opd = (Addr)(*sym_avmas_out).main - (Addr)(di->opd_avma);
586 if (offset_in_opd < 0 || offset_in_opd >= di->opd_size) {
587 if (TRACE_SYMTAB_ENABLED) {
588 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
589 "di.gesi.6a", sym_name_ioff);
590 TRACE_SYMTAB(" ignore -- invalid OPD offset: %s\n", sym_name);
591 if (sym_name) ML_(dinfo_free)(sym_name);
593 return False;
596 /* Now we want to know what's at that offset in the .opd
597 section. We can't look in the running image since it won't
598 necessarily have been mapped. But we can consult the oimage.
599 opd_img is the start address of the .opd in the oimage.
600 Hence: */
602 ULong fn_descr[2]; /* is actually 3 words, but we need only 2 */
603 if (!ML_(img_valid)(escn_opd->img, escn_opd->ioff + offset_in_opd,
604 sizeof(fn_descr))) {
605 if (TRACE_SYMTAB_ENABLED) {
606 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
607 "di.gesi.6b", sym_name_ioff);
608 TRACE_SYMTAB(" ignore -- invalid OPD fn_descr offset: %s\n",
609 sym_name);
610 if (sym_name) ML_(dinfo_free)(sym_name);
613 return False;
616 /* This can't fail now, because we just checked the offset
617 above. */
618 ML_(img_get)(&fn_descr[0], escn_opd->img,
619 escn_opd->ioff + offset_in_opd, sizeof(fn_descr));
621 if (details)
622 TRACE_SYMTAB("opdXXY: offset %d, fn_descr %p\n",
623 offset_in_opd, fn_descr);
624 if (details)
625 TRACE_SYMTAB("opdXXZ: *fn_descr %p\n", (void*)(fn_descr[0]));
627 /* opd_bias is the what we have to add to SVMAs found in .opd to
628 get plausible .text AVMAs for the entry point, and .data
629 AVMAs (presumably) for the TOC locations. We use the caller
630 supplied value (which is di->text_bias) for both of these.
631 Not sure why that is correct - it seems to work, and sounds
632 OK for fn_descr[0], but surely we need to use the data bias
633 and not the text bias for fn_descr[1] ? Oh Well.
635 (*sym_avmas_out).main = fn_descr[0] + opd_bias;
636 SET_TOCPTR_AVMA(*sym_avmas_out, fn_descr[1] + opd_bias);
637 *from_opd_out = True;
638 is_in_opd = True;
640 /* Do a final sanity check: if the symbol falls outside the
641 DebugInfo's mapped range, ignore it. Since (*sym_avmas_out).main has
642 been updated, that can be achieved simply by falling through
643 to the test below. */
645 # endif /* ppc64-linux nasty hack */
648 /* Here's yet another ppc64-linux hack. Get rid of leading dot if
649 the symbol is outside .opd. */
650 # if defined(VGP_ppc64be_linux)
651 if (di->opd_size > 0
652 && !is_in_opd
653 && *sym_name_out_ioff != DiOffT_INVALID
654 && ML_(img_get_UChar)(escn_strtab->img, *sym_name_out_ioff) == '.') {
655 vg_assert(!(*from_opd_out));
656 (*sym_name_out_ioff)++;
658 # endif
660 /* If no part of the symbol falls within the mapped range,
661 ignore it. */
663 in_text
664 = di->text_present
665 && di->text_size > 0
666 && !((*sym_avmas_out).main + *sym_size_out <= di->text_avma
667 || (*sym_avmas_out).main >= di->text_avma + di->text_size);
669 in_data
670 = di->data_present
671 && di->data_size > 0
672 && !((*sym_avmas_out).main + *sym_size_out <= di->data_avma
673 || (*sym_avmas_out).main >= di->data_avma + di->data_size);
675 in_sdata
676 = di->sdata_present
677 && di->sdata_size > 0
678 && !((*sym_avmas_out).main + *sym_size_out <= di->sdata_avma
679 || (*sym_avmas_out).main >= di->sdata_avma + di->sdata_size);
681 in_rodata
682 = di->rodata_present
683 && di->rodata_size > 0
684 && !((*sym_avmas_out).main + *sym_size_out <= di->rodata_avma
685 || (*sym_avmas_out).main >= di->rodata_avma + di->rodata_size);
687 in_bss
688 = di->bss_present
689 && di->bss_size > 0
690 && !((*sym_avmas_out).main + *sym_size_out <= di->bss_avma
691 || (*sym_avmas_out).main >= di->bss_avma + di->bss_size);
693 in_sbss
694 = di->sbss_present
695 && di->sbss_size > 0
696 && !((*sym_avmas_out).main + *sym_size_out <= di->sbss_avma
697 || (*sym_avmas_out).main >= di->sbss_avma + di->sbss_size);
700 if (*is_text_out) {
701 /* This used to reject any symbol falling outside the text
702 segment ("if (!in_text) ..."). Now it is relaxed slightly,
703 to reject only symbols which fall outside the area mapped
704 r-x. This is in accordance with r7427. See
705 "Comment_Regarding_Text_Range_Checks" in storage.c for
706 background. */
707 Bool in_rx;
708 vg_assert(di->fsm.have_rx_map);
709 /* This could actually wrap around and cause
710 ML_(find_rx_mapping) to assert. But that seems so unlikely,
711 let's wait for it to happen before fixing it. */
712 in_rx = (ML_(find_rx_mapping)(
714 (*sym_avmas_out).main,
715 (*sym_avmas_out).main + *sym_size_out - 1) != NULL);
716 if (in_text)
717 vg_assert(in_rx);
718 if (!in_rx) {
719 TRACE_SYMTAB(
720 "ignore -- %#lx .. %#lx outside .text svma range %#lx .. %#lx\n",
721 (*sym_avmas_out).main, (*sym_avmas_out).main + *sym_size_out - 1,
722 di->text_avma,
723 di->text_avma + di->text_size - 1);
724 return False;
726 } else {
727 if (!(in_data || in_sdata || in_rodata || in_bss || in_sbss)) {
728 TRACE_SYMTAB(
729 "ignore -- %#lx .. %#lx outside .data / .sdata / .rodata "
730 "/ .bss / .sbss svma ranges\n",
731 (*sym_avmas_out).main, (*sym_avmas_out).main + *sym_size_out - 1);
732 return False;
736 # if defined(VGP_ppc64be_linux)
737 if (di->opd_present && di->opd_size > 0) {
738 vg_assert((*sym_avmas_out).main + *sym_size_out <= di->opd_avma
739 || (*sym_avmas_out).main >= di->opd_avma + di->opd_size);
741 #endif
743 # if defined(VGP_ppc64le_linux)
744 /* PPC64 LE ABI uses three bits in the st_other field to indicate the number
745 * of instructions between the function's global and local entry points. An
746 * offset of 0 indicates that there is one entry point. The value must be:
748 * 0 - one entry point, local and global are the same
749 * 1 - reserved
750 * 2 - local entry point is one instruction after the global entry point
751 * 3 - local entry point is two instructions after the global entry point
752 * 4 - local entry point is four instructions after the global entry point
753 * 5 - local entry point is eight instructions after the global entry point
754 * 6 - local entry point is sixteen instructions after the global entry point
755 * 7 - reserved
757 * Extract the three bit field from the other field is done by:
758 * (other_field & STO_PPC64_LOCAL_MASK) >> STO_PPC_LOCAL_BIT
760 * where the #define values are given in include/elf/powerpc.h file for
761 * the PPC binutils.
763 * conversion of the three bit field to bytes is given by
765 * ((1 << bit_field) >> 2) << 2
768 #define STO_PPC64_LOCAL_BIT 5
769 #define STO_PPC64_LOCAL_MASK (7 << STO_PPC64_LOCAL_BIT)
771 unsigned int bit_field, dist_to_local_entry;
772 /* extract the other filed */
773 bit_field = (sym->st_other & STO_PPC64_LOCAL_MASK) >> STO_PPC64_LOCAL_BIT;
775 if ((bit_field > 0) && (bit_field < 7)) {
776 /* store the local entry point address */
777 dist_to_local_entry = ((1 << bit_field) >> 2) << 2;
778 SET_LOCAL_EP_AVMA(*sym_avmas_out,
779 (*sym_avmas_out).main + dist_to_local_entry);
781 if (TRACE_SYMTAB_ENABLED) {
782 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
783 "di.gesi.5", sym_name_ioff);
784 VG_(printf)("Local entry point: %s at %#010x\n",
785 sym_name,
786 (unsigned int)GET_LOCAL_EP_AVMA(*sym_avmas_out));
790 # endif
792 /* Acquire! */
793 return True;
797 /* Read an ELF symbol table (normal or dynamic). This one is for the
798 "normal" case ({x86,amd64,ppc32,arm,mips32,mips64, ppc64le}-linux). */
799 static
800 __attribute__((unused)) /* not referred to on all targets */
801 void read_elf_symtab__normal(
802 struct _DebugInfo* di, const HChar* tab_name,
803 DiSlice* escn_symtab,
804 DiSlice* escn_strtab,
805 DiSlice* escn_opd, /* ppc64be-linux only */
806 Bool symtab_in_debug
809 if (escn_strtab->img == NULL || escn_symtab->img == NULL) {
810 HChar buf[VG_(strlen)(tab_name) + 40];
811 VG_(sprintf)(buf, " object doesn't have a %s", tab_name);
812 ML_(symerr)(di, False, buf);
813 return;
816 TRACE_SYMTAB("\n--- Reading (ELF, standard) %s (%llu entries) ---\n",
817 tab_name, escn_symtab->szB/sizeof(ElfXX_Sym) );
819 /* Perhaps should start at i = 1; ELF docs suggest that entry
820 0 always denotes 'unknown symbol'. */
821 Word i;
822 for (i = 1; i < (Word)(escn_symtab->szB/sizeof(ElfXX_Sym)); i++) {
823 ElfXX_Sym sym;
824 ML_(img_get)(&sym, escn_symtab->img,
825 escn_symtab->ioff + i * sizeof(ElfXX_Sym), sizeof(sym));
826 DiOffT sym_name = escn_strtab->ioff + sym.st_name;
827 Addr sym_svma = sym.st_value;
829 if (di->trace_symtab)
830 show_raw_elf_symbol(escn_strtab->img, i,
831 &sym, sym_name, sym_svma, False);
833 SymAVMAs sym_avmas_really;
834 Int sym_size = 0;
835 Bool from_opd = False, is_text = False, is_ifunc = False;
836 Bool is_global = False;
837 DiOffT sym_name_really = DiOffT_INVALID;
838 sym_avmas_really.main = 0;
839 SET_TOCPTR_AVMA(sym_avmas_really, 0);
840 SET_LOCAL_EP_AVMA(sym_avmas_really, 0);
841 if (get_elf_symbol_info(di, &sym, sym_name, escn_strtab,
842 sym_svma, symtab_in_debug,
843 escn_opd, di->text_bias,
844 &sym_name_really,
845 &sym_avmas_really,
846 &sym_size,
847 &from_opd, &is_text, &is_ifunc, &is_global)) {
849 DiSym disym;
850 VG_(memset)(&disym, 0, sizeof(disym));
851 HChar* cstr = ML_(img_strdup)(escn_strtab->img,
852 "di.res__n.1", sym_name_really);
853 disym.avmas = sym_avmas_really;
854 disym.pri_name = ML_(addStr) ( di, cstr, -1 );
855 disym.sec_names = NULL;
856 disym.size = sym_size;
857 disym.isText = is_text;
858 disym.isIFunc = is_ifunc;
859 disym.isGlobal = is_global;
860 if (cstr) { ML_(dinfo_free)(cstr); cstr = NULL; }
861 vg_assert(disym.pri_name);
862 vg_assert(GET_TOCPTR_AVMA(disym.avmas) == 0);
863 /* has no role except on ppc64be-linux */
864 ML_(addSym) ( di, &disym );
866 if (TRACE_SYMTAB_ENABLED) {
867 TRACE_SYMTAB(" rec(%c) [%4ld]: "
868 " val %#010lx, sz %4d %s\n",
869 is_text ? 't' : 'd',
871 disym.avmas.main,
872 (Int)disym.size,
873 disym.pri_name
875 if (GET_LOCAL_EP_AVMA(disym.avmas) != 0) {
876 TRACE_SYMTAB(" local entry point %#010lx\n",
877 GET_LOCAL_EP_AVMA(disym.avmas));
886 /* Read an ELF symbol table (normal or dynamic). This one is for
887 ppc64be-linux, which requires special treatment. */
889 typedef
890 struct {
891 Addr addr;
892 DiOffT name;
893 /* We have to store also the DiImage* so as to give context for
894 |name|. This is not part of the key (in terms of lookup) but
895 there's no easy other way to do this. Ugly. */
896 DiImage* img;
898 TempSymKey;
900 typedef
901 struct {
902 TempSymKey key;
903 Addr tocptr;
904 Int size;
905 Bool from_opd;
906 Bool is_text;
907 Bool is_ifunc;
908 Bool is_global;
910 TempSym;
912 static Word cmp_TempSymKey ( const TempSymKey* key1, const TempSym* elem2 )
914 /* Stay sane ... */
915 vg_assert(key1->img == elem2->key.img);
916 vg_assert(key1->img != NULL);
917 if (key1->addr < elem2->key.addr) return -1;
918 if (key1->addr > elem2->key.addr) return 1;
919 vg_assert(key1->name != DiOffT_INVALID);
920 vg_assert(elem2->key.name != DiOffT_INVALID);
921 return (Word)ML_(img_strcmp)(key1->img, key1->name, elem2->key.name);
924 static
925 __attribute__((unused)) /* not referred to on all targets */
926 void read_elf_symtab__ppc64be_linux(
927 struct _DebugInfo* di, const HChar* tab_name,
928 DiSlice* escn_symtab,
929 DiSlice* escn_strtab,
930 DiSlice* escn_opd, /* ppc64be-linux only */
931 Bool symtab_in_debug
934 Word i;
935 Int old_size;
936 Bool modify_size, modify_tocptr;
937 OSet *oset;
938 TempSymKey key;
939 TempSym *elem;
940 TempSym *prev;
942 if (escn_strtab->img == NULL || escn_symtab->img == NULL) {
943 HChar buf[VG_(strlen)(tab_name) + 40];
944 VG_(sprintf)(buf, " object doesn't have a %s", tab_name);
945 ML_(symerr)(di, False, buf);
946 return;
949 TRACE_SYMTAB("\n--- Reading (ELF, ppc64be-linux) %s (%llu entries) ---\n",
950 tab_name, escn_symtab->szB/sizeof(ElfXX_Sym) );
952 oset = VG_(OSetGen_Create)( offsetof(TempSym,key),
953 (OSetCmp_t)cmp_TempSymKey,
954 ML_(dinfo_zalloc), "di.respl.1",
955 ML_(dinfo_free) );
957 /* Perhaps should start at i = 1; ELF docs suggest that entry
958 0 always denotes 'unknown symbol'. */
959 for (i = 1; i < (Word)(escn_symtab->szB/sizeof(ElfXX_Sym)); i++) {
960 ElfXX_Sym sym;
961 ML_(img_get)(&sym, escn_symtab->img,
962 escn_symtab->ioff + i * sizeof(ElfXX_Sym), sizeof(sym));
963 DiOffT sym_name = escn_strtab->ioff + sym.st_name;
964 Addr sym_svma = sym.st_value;
966 if (di->trace_symtab)
967 show_raw_elf_symbol(escn_strtab->img, i,
968 &sym, sym_name, sym_svma, True);
970 SymAVMAs sym_avmas_really;
971 Int sym_size = 0;
972 Bool from_opd = False, is_text = False, is_ifunc = False;
973 Bool is_global = False;
974 DiOffT sym_name_really = DiOffT_INVALID;
975 DiSym disym;
976 VG_(memset)(&disym, 0, sizeof(disym));
977 sym_avmas_really.main = 0;
978 SET_TOCPTR_AVMA(sym_avmas_really, 0);
979 SET_LOCAL_EP_AVMA(sym_avmas_really, 0);
980 if (get_elf_symbol_info(di, &sym, sym_name, escn_strtab,
981 sym_svma, symtab_in_debug,
982 escn_opd, di->text_bias,
983 &sym_name_really,
984 &sym_avmas_really,
985 &sym_size,
986 &from_opd, &is_text, &is_ifunc, &is_global)) {
988 /* Check if we've seen this (name,addr) key before. */
989 key.addr = sym_avmas_really.main;
990 key.name = sym_name_really;
991 key.img = escn_strtab->img;
992 prev = VG_(OSetGen_Lookup)( oset, &key );
994 if (prev) {
996 /* Seen it before. Fold in whatever new info we can. */
997 modify_size = False;
998 modify_tocptr = False;
999 old_size = 0;
1001 if (prev->from_opd && !from_opd
1002 && (prev->size == 24 || prev->size == 16)
1003 && sym_size != prev->size) {
1004 /* Existing one is an opd-redirect, with a bogus size,
1005 so the only useful new fact we have is the real size
1006 of the symbol. */
1007 modify_size = True;
1008 old_size = prev->size;
1009 prev->size = sym_size;
1011 else
1012 if (!prev->from_opd && from_opd
1013 && (sym_size == 24 || sym_size == 16)) {
1014 /* Existing one is non-opd, new one is opd. What we
1015 can acquire from the new one is the TOC ptr to be
1016 used. Since the existing sym is non-toc, it
1017 shouldn't currently have an known TOC ptr. */
1018 vg_assert(prev->tocptr == 0);
1019 modify_tocptr = True;
1020 prev->tocptr = GET_TOCPTR_AVMA(sym_avmas_really);
1022 else {
1023 /* ignore. can we do better here? */
1026 /* Only one or the other is possible (I think) */
1027 vg_assert(!(modify_size && modify_tocptr));
1029 if (modify_size && di->trace_symtab) {
1030 VG_(printf)(" modify (old sz %4d) "
1031 " val %#010lx, toc %#010lx, sz %4d %llu\n",
1032 old_size,
1033 prev->key.addr,
1034 prev->tocptr,
1035 prev->size,
1036 prev->key.name
1039 if (modify_tocptr && di->trace_symtab) {
1040 VG_(printf)(" modify (upd tocptr) "
1041 " val %#010lx, toc %#010lx, sz %4d %llu\n",
1042 prev->key.addr,
1043 prev->tocptr,
1044 prev->size,
1045 prev->key.name
1049 } else {
1051 /* A new (name,addr) key. Add and continue. */
1052 elem = VG_(OSetGen_AllocNode)(oset, sizeof(TempSym));
1053 elem->key = key;
1054 elem->tocptr = GET_TOCPTR_AVMA(sym_avmas_really);
1055 elem->size = sym_size;
1056 elem->from_opd = from_opd;
1057 elem->is_text = is_text;
1058 elem->is_ifunc = is_ifunc;
1059 elem->is_global = is_global;
1060 VG_(OSetGen_Insert)(oset, elem);
1061 if (di->trace_symtab) {
1062 HChar* str = ML_(img_strdup)(escn_strtab->img, "di.respl.2",
1063 elem->key.name);
1064 VG_(printf)(" to-oset [%4ld]: "
1065 " val %#010lx, toc %#010lx, sz %4d %s\n",
1067 elem->key.addr,
1068 elem->tocptr,
1069 (Int) elem->size,
1072 if (str) ML_(dinfo_free)(str);
1079 /* All the syms that matter are in the oset. Now pull them out,
1080 build a "standard" symbol table, and nuke the oset. */
1082 i = 0;
1083 VG_(OSetGen_ResetIter)( oset );
1085 while ( (elem = VG_(OSetGen_Next)(oset)) ) {
1086 DiSym disym;
1087 VG_(memset)(&disym, 0, sizeof(disym));
1088 HChar* cstr = ML_(img_strdup)(escn_strtab->img,
1089 "di.res__ppc64.1", elem->key.name);
1090 disym.avmas.main = elem->key.addr;
1091 SET_TOCPTR_AVMA(disym.avmas, elem->tocptr);
1092 SET_LOCAL_EP_AVMA(disym.avmas, 0); // ppc64be does not use local_ep.
1093 disym.pri_name = ML_(addStr) ( di, cstr, -1 );
1094 disym.sec_names = NULL;
1095 disym.size = elem->size;
1096 disym.isText = elem->is_text;
1097 disym.isIFunc = elem->is_ifunc;
1098 disym.isGlobal = elem->is_global;
1099 if (cstr) { ML_(dinfo_free)(cstr); cstr = NULL; }
1100 vg_assert(disym.pri_name != NULL);
1102 ML_(addSym) ( di, &disym );
1103 if (di->trace_symtab) {
1104 VG_(printf)(" rec(%c%c%c) [%4ld]: "
1105 " val %#010lx, toc %#010lx, sz %4d %s\n",
1106 disym.isText ? 't' : 'd',
1107 disym.isIFunc ? 'i' : '-',
1108 disym.isGlobal ? 'g' : 'l',
1110 disym.avmas.main,
1111 GET_TOCPTR_AVMA(disym.avmas),
1112 (Int) disym.size,
1113 disym.pri_name
1116 i++;
1119 VG_(OSetGen_Destroy)( oset );
1122 #if defined(VGO_freebsd)
1125 * read_and_set_osrel
1127 * "osrel" is in an Elf note. It has values such as 1201000 for FreeBSD 12.1
1128 * Some of the behaviour related to SIGSEGV and SIGBUS signals depends on the
1129 * kernel reading this value.
1131 * However in the case of Valgrind, the host is strictly statically linked and
1132 * does not contain the NT_FREEBSD_ABI_TAG note. And even if it did, we want to
1133 * override the value with that of the guest.
1135 * At some later date we might want to look at the value of "fctl0" (note with the
1136 * NT_FREEBSD_FEATURE_CTL type). This seems to be related to Address Space Layout
1137 * Randomization. No hurry at the moment.
1139 * See /usr/src/sys/kern/imgact_elf.c for details on how the kernel reads these
1140 * notes.
1142 static
1143 void read_and_set_osrel(DiImage* img)
1145 if (is_elf_object_file_by_DiImage(img, False)) {
1146 Word i;
1148 ElfXX_Ehdr ehdr;
1149 ML_(img_get)(&ehdr, img, 0, sizeof(ehdr));
1151 /* only set osrel for executable files, not for subsequent shared libraries */
1152 if (ehdr.e_type != ET_EXEC) {
1153 return;
1156 /* Skip the phdrs when we have to search the shdrs. In separate
1157 .debug files the phdrs might not be valid (they are a copy of
1158 the main ELF file) and might trigger assertions when getting
1159 image notes based on them. */
1160 for (i = 0; i < ehdr.e_phnum; i++) {
1161 ElfXX_Phdr phdr;
1162 ML_(img_get)(&phdr, img,
1163 ehdr.e_phoff + i * ehdr.e_phentsize, sizeof(phdr));
1165 if (phdr.p_type == PT_NOTE) {
1166 ElfXX_Off note_ioff = phdr.p_offset;
1168 while (note_ioff < phdr.p_offset + phdr.p_filesz) {
1169 ElfXX_Nhdr note[2];
1170 ML_(img_get)(note, img, (DiOffT)note_ioff, sizeof(note));
1171 DiOffT name_ioff = note_ioff + sizeof(ElfXX_Nhdr);
1172 //DiOffT desc_ioff = name_ioff + ((note[0].n_namesz + 3) & ~3);
1173 if (ML_(img_strcmp_c)(img, name_ioff, "FreeBSD") == 0
1174 && note[0].n_type == VKI_NT_FREEBSD_ABI_TAG) {
1176 u_int32_t osrel = note[1].n_type;
1177 int name[4];
1178 name[0] = CTL_KERN;
1179 name[1] = KERN_PROC;
1180 name[2] = KERN_PROC_OSREL;
1181 name[3] = VG_(getpid)();
1182 SizeT newlen = sizeof(osrel);
1183 Int error = VG_(sysctl)(name, 4, NULL, NULL, &osrel, newlen);
1184 if (error == -1) {
1185 VG_(message)(Vg_DebugMsg, "Warning: failed to set osrel for current process with value %u\n", osrel);
1186 } else {
1187 if (VG_(clo_verbosity) > 1) {
1188 VG_(message)(Vg_DebugMsg, "Set osrel for current process with value %u\n", osrel);
1192 note_ioff = note_ioff + sizeof(ElfXX_Nhdr)
1193 + ((note[0].n_namesz + 3) & ~3)
1194 + ((note[0].n_descsz + 3) & ~3);
1201 #endif
1204 * Look for a build-id in an ELF image. The build-id specification
1205 * can be found here:
1207 * http://fedoraproject.org/wiki/RolandMcGrath/BuildID
1209 * Returned string must be freed by the caller.
1211 static
1212 HChar* find_buildid(DiImage* img, Bool rel_ok, Bool search_shdrs)
1214 HChar* buildid = NULL;
1216 # ifdef NT_GNU_BUILD_ID
1217 if (is_elf_object_file_by_DiImage(img, rel_ok)) {
1218 Word i;
1220 ElfXX_Ehdr ehdr;
1221 ML_(img_get)(&ehdr, img, 0, sizeof(ehdr));
1222 /* Skip the phdrs when we have to search the shdrs. In separate
1223 .debug files the phdrs might not be valid (they are a copy of
1224 the main ELF file) and might trigger assertions when getting
1225 image notes based on them. */
1226 for (i = 0; !search_shdrs && i < ehdr.e_phnum; i++) {
1227 ElfXX_Phdr phdr;
1228 ML_(img_get)(&phdr, img,
1229 ehdr.e_phoff + i * ehdr.e_phentsize, sizeof(phdr));
1231 if (phdr.p_type == PT_NOTE) {
1232 ElfXX_Off note_ioff = phdr.p_offset;
1234 while (note_ioff < phdr.p_offset + phdr.p_filesz) {
1235 ElfXX_Nhdr note;
1236 ML_(img_get)(&note, img, (DiOffT)note_ioff, sizeof(note));
1237 DiOffT name_ioff = note_ioff + sizeof(ElfXX_Nhdr);
1238 DiOffT desc_ioff = name_ioff + ((note.n_namesz + 3) & ~3);
1239 if (ML_(img_strcmp_c)(img, name_ioff, ELF_NOTE_GNU) == 0
1240 && note.n_type == NT_GNU_BUILD_ID) {
1241 buildid = ML_(dinfo_zalloc)("di.fbi.1",
1242 note.n_descsz * 2 + 1);
1243 Word j;
1244 for (j = 0; j < note.n_descsz; j++) {
1245 UChar desc_j = ML_(img_get_UChar)(img, desc_ioff + j);
1246 VG_(sprintf)(buildid + VG_(strlen)(buildid),
1247 "%02x", (UInt)desc_j);
1251 note_ioff = note_ioff + sizeof(ElfXX_Nhdr)
1252 + ((note.n_namesz + 3) & ~3)
1253 + ((note.n_descsz + 3) & ~3);
1258 /* Normally we would only search shdrs for ET_REL files, but when
1259 we search for a separate .debug file phdrs might not be there
1260 (they are never loaded) or have been corrupted, so try again
1261 against shdrs. */
1262 if (buildid || (!rel_ok && !search_shdrs))
1263 return buildid;
1265 for (i = 0; i < ehdr.e_shnum; i++) {
1266 ElfXX_Shdr shdr;
1267 ML_(img_get)(&shdr, img,
1268 ehdr.e_shoff + i * ehdr.e_shentsize, sizeof(shdr));
1270 if (shdr.sh_type == SHT_NOTE) {
1271 ElfXX_Off note_ioff = shdr.sh_offset;
1273 while (note_ioff < shdr.sh_offset + shdr.sh_size) {
1274 ElfXX_Nhdr note;
1275 ML_(img_get)(&note, img, (DiOffT)note_ioff, sizeof(note));
1276 DiOffT name_ioff = note_ioff + sizeof(ElfXX_Nhdr);
1277 DiOffT desc_ioff = name_ioff + ((note.n_namesz + 3) & ~3);
1279 if (ML_(img_strcmp_c)(img, name_ioff, ELF_NOTE_GNU) == 0
1280 && note.n_type == NT_GNU_BUILD_ID) {
1281 buildid = ML_(dinfo_zalloc)("di.fbi.2",
1282 note.n_descsz * 2 + 1);
1283 Word j;
1284 for (j = 0; j < note.n_descsz; j++) {
1285 UChar desc_j = ML_(img_get_UChar)(img, desc_ioff + j);
1286 VG_(sprintf)(buildid + VG_(strlen)(buildid),
1287 "%02x", (UInt)desc_j);
1291 note_ioff = note_ioff + sizeof(ElfXX_Nhdr)
1292 + ((note.n_namesz + 3) & ~3)
1293 + ((note.n_descsz + 3) & ~3);
1298 # endif /* def NT_GNU_BUILD_ID */
1300 return buildid;
1304 /* Try and open a separate debug file, ignoring any where the CRC does
1305 not match the value from the main object file. Returned DiImage
1306 must be discarded by the caller.
1308 If |serverAddr| is NULL, |name| is expected to be a fully qualified
1309 (absolute) path to the file in the local filesystem. If
1310 |serverAddr| is non-NULL, it is expected to be an IPv4 and port
1311 spec of the form "d.d.d.d:d" or "d.d.d.d", and |name| is expected
1312 to be a plain filename (no path components at all).
1314 static
1315 DiImage* open_debug_file( const HChar* name, const HChar* buildid, UInt crc,
1316 Bool rel_ok, const HChar* serverAddr )
1318 DiImage* dimg
1319 = serverAddr ? ML_(img_from_di_server)(name, serverAddr)
1320 : ML_(img_from_local_file)(name);
1321 if (dimg == NULL)
1322 return NULL;
1324 if (VG_(clo_verbosity) > 1) {
1325 if (serverAddr)
1326 VG_(message)(Vg_DebugMsg, " Considering %s on server %s ..\n",
1327 name, serverAddr);
1328 else
1329 VG_(message)(Vg_DebugMsg, " Considering %s ..\n", name);
1332 /* We will always check the crc if we have one (altfiles don't have one)
1333 for now because we might be opening the main file again by any other
1334 name, and that obviously also has the same buildid. More efficient
1335 would be an fstat bases check or a check that the file actually
1336 contains .debug* sections. */
1337 if (buildid && crc == 0) {
1338 HChar* debug_buildid = find_buildid(dimg, rel_ok, True);
1339 if (debug_buildid == NULL || VG_(strcmp)(buildid, debug_buildid) != 0) {
1340 ML_(img_done)(dimg);
1341 if (VG_(clo_verbosity) > 1)
1342 VG_(message)(Vg_DebugMsg,
1343 " .. build-id mismatch (found %s wanted %s)\n",
1344 debug_buildid, buildid);
1345 ML_(dinfo_free)(debug_buildid);
1346 return NULL;
1348 ML_(dinfo_free)(debug_buildid);
1349 if (VG_(clo_verbosity) > 1)
1350 VG_(message)(Vg_DebugMsg, " .. build-id is valid\n");
1351 } else {
1352 UInt calccrc = ML_(img_calc_gnu_debuglink_crc32)(dimg);
1353 if (calccrc != crc) {
1354 ML_(img_done)(dimg);
1355 if (VG_(clo_verbosity) > 1)
1356 VG_(message)(Vg_DebugMsg,
1357 " .. CRC mismatch (computed %08x wanted %08x)\n", calccrc, crc);
1358 return NULL;
1361 if (VG_(clo_verbosity) > 1)
1362 VG_(message)(Vg_DebugMsg, " .. CRC is valid\n");
1365 return dimg;
1368 #if defined(VGO_linux)
1369 /* Return the path of the debuginfod-find executable. */
1370 static
1371 const HChar* debuginfod_find_path( void )
1373 static const HChar* path = (const HChar*) -1;
1375 if (path == (const HChar*) -1) {
1376 if (VG_(getenv)("DEBUGINFOD_URLS") == NULL
1377 || VG_(strcmp)("", VG_(getenv("DEBUGINFOD_URLS"))) == 0)
1378 path = NULL;
1379 else
1380 path = VG_(find_executable)("debuginfod-find");
1383 return path;
1386 /* Try to find a separate debug file with |buildid| via debuginfod. If found,
1387 return its DiImage. Searches for a local debuginfod-find executable and
1388 runs it in a child process in order to download the debug file. */
1389 static
1390 DiImage* find_debug_file_debuginfod( const HChar* objpath,
1391 HChar** debugpath,
1392 const HChar* buildid,
1393 const UInt crc, Bool rel_ok )
1395 # define BUF_SIZE 4096
1396 Int out_fds[2], err_fds[2]; /* pipe fds */
1397 DiImage* dimg = NULL; /* the img we found */
1398 HChar buf[BUF_SIZE]; /* executable output buffer */
1399 const HChar* path; /* executable path */
1400 SizeT len; /* number of bytes read int buf */
1401 Int ret; /* result of read call */
1403 if (buildid == NULL)
1404 return NULL;
1406 if ((path = debuginfod_find_path()) == NULL)
1407 return NULL;
1409 if (VG_(pipe)(out_fds) != 0
1410 || VG_(pipe)(err_fds) != 0)
1411 return NULL;
1413 if (VG_(clo_verbosity) > 1)
1414 VG_(umsg)("Downloading debug info for %s...\n", objpath);
1416 /* Run debuginfod-find to query servers for the debuginfo. */
1417 Int pid = VG_(fork)();
1418 if (pid == 0) {
1419 const HChar *argv[4] = { path, "debuginfo", buildid, (HChar*)0 };
1421 /* Redirect stdout and stderr */
1422 SysRes res = VG_(dup2)(out_fds[1], 1);
1423 if (sr_Res(res) < 0)
1424 VG_(exit)(1);
1426 res = VG_(dup2)(err_fds[1], 2);
1427 if (sr_Res(res) < 0)
1428 VG_(exit)(1);
1430 /* Disable extra stderr output since it does not play well with umesg */
1431 VG_(env_unsetenv)(VG_(client_envp), "DEBUGINFOD_VERBOSE", NULL);
1432 VG_(env_unsetenv)(VG_(client_envp), "DEBUGINFOD_PROGRESS", NULL);
1434 VG_(close)(out_fds[0]);
1435 VG_(close)(err_fds[0]);
1436 VG_(execv)(argv[0], argv);
1438 /* If we are still alive here, execv failed. */
1439 VG_(exit)(1);
1442 VG_(close)(out_fds[1]);
1443 VG_(close)(err_fds[1]);
1445 if (pid < 0) {
1446 if (VG_(clo_verbosity) > 1)
1447 VG_(umsg)("Server Error\n");
1448 goto out;
1450 VG_(waitpid)(pid, NULL, 0);
1452 /* Set dimg if download was successful. */
1453 len = 0;
1454 ret = -1;
1455 while (len >= 0 && len < BUF_SIZE) {
1456 ret = VG_(read)(out_fds[0], buf + len, BUF_SIZE - len);
1457 if (ret <= 0)
1458 break;
1459 len += ret;
1461 if (ret >= 0 && len > 0
1462 && buf[0] == '/' && buf[len-1] == '\n') {
1464 /* Remove newline from filename before trying to open debug file */
1465 buf[len-1] = '\0';
1466 dimg = open_debug_file(buf, buildid, crc, rel_ok, NULL);
1467 if (dimg != NULL) {
1468 /* Success */
1469 if (*debugpath)
1470 ML_(dinfo_free)(*debugpath);
1472 *debugpath = ML_(dinfo_strdup)("di.fdfd.1", buf);
1473 if (VG_(clo_verbosity) > 1)
1474 VG_(umsg)("Successfully downloaded debug file for %s\n",
1475 objpath);
1476 goto out;
1480 /* Download failed so try to print error message. */
1481 HChar* nl;
1482 if (VG_(read)(err_fds[0], buf, BUF_SIZE) > 0
1483 && (nl = VG_(strchr)(buf, '\n'))) {
1484 *nl = '\0';
1485 if (VG_(clo_verbosity) > 1)
1486 VG_(umsg)("%s\n", buf);
1487 } else
1488 if (VG_(clo_verbosity) > 1)
1489 VG_(umsg)("Server Error\n");
1491 out:
1492 VG_(close)(out_fds[0]);
1493 VG_(close)(err_fds[0]);
1494 return dimg;
1496 #endif
1498 /* Try to find a separate debug file for a given object file. If
1499 found, return its DiImage, which should be freed by the caller. If
1500 |buildid| is non-NULL, then a debug object matching it is
1501 acceptable. If |buildid| is NULL or doesn't specify a findable
1502 debug object, then we look in various places to find a file with
1503 the specified CRC. And if that doesn't work out then we give
1504 up. */
1505 static
1506 DiImage* find_debug_file( struct _DebugInfo* di,
1507 const HChar* objpath, const HChar* buildid,
1508 const HChar* debugname, UInt crc, Bool rel_ok )
1510 const HChar* extrapath = VG_(clo_extra_debuginfo_path);
1511 const HChar* serverpath = VG_(clo_debuginfo_server);
1513 DiImage* dimg = NULL; /* the img that we found */
1514 HChar* debugpath = NULL; /* where we found it */
1516 if (buildid != NULL) {
1517 debugpath = ML_(dinfo_zalloc)("di.fdf.1",
1518 VG_(strlen)(buildid) + 33);
1520 VG_(sprintf)(debugpath, "/usr/lib/debug/.build-id/%c%c/%s.debug",
1521 buildid[0], buildid[1], buildid + 2);
1523 dimg = open_debug_file(debugpath, buildid, 0, rel_ok, NULL);
1524 if (!dimg) {
1525 ML_(dinfo_free)(debugpath);
1526 debugpath = NULL;
1530 if (dimg == NULL && debugname != NULL) {
1531 HChar *objdir = ML_(dinfo_strdup)("di.fdf.2", objpath);
1532 HChar *usrmerge_objdir;
1533 HChar *objdirptr;
1535 if ((objdirptr = VG_(strrchr)(objdir, '/')) != NULL)
1536 *objdirptr = '\0';
1538 if ((objdirptr = VG_(strstr)(objdir, "usr")) != NULL)
1539 usrmerge_objdir = objdirptr + VG_(strlen)("usr");
1540 else
1541 usrmerge_objdir = NULL;
1543 debugpath = ML_(dinfo_zalloc)(
1544 "di.fdf.3",
1545 VG_(strlen)(objdir) + VG_(strlen)(debugname) + 64
1546 + (extrapath ? VG_(strlen)(extrapath) : 0)
1547 + (serverpath ? VG_(strlen)(serverpath) : 0));
1549 # define TRY_OBJDIR(format, ...) \
1550 do { \
1551 VG_(sprintf)(debugpath, format, __VA_ARGS__); \
1552 dimg = open_debug_file(debugpath, buildid, crc, rel_ok, NULL); \
1553 if (dimg != NULL) goto dimg_ok; \
1554 } while (0);
1556 # define TRY_OBJDIR_USRMERGE_OBJDIR(format) \
1557 do { \
1558 TRY_OBJDIR(format, objdir, debugname); \
1559 if (usrmerge_objdir != NULL) { \
1560 TRY_OBJDIR(format, usrmerge_objdir, debugname); \
1562 } while (0)
1564 if (debugname[0] == '/') {
1565 TRY_OBJDIR("%s", debugname);
1568 TRY_OBJDIR_USRMERGE_OBJDIR("%s/%s");
1569 TRY_OBJDIR_USRMERGE_OBJDIR("%s/.debug/%s");
1570 TRY_OBJDIR_USRMERGE_OBJDIR("/usr/lib/debug%s/%s");
1572 if (extrapath) {
1573 TRY_OBJDIR("%s%s/%s", extrapath, objdir, debugname);
1574 if (usrmerge_objdir != NULL)
1575 TRY_OBJDIR("%s%s/%s", extrapath, usrmerge_objdir, debugname);
1577 # undef TRY_OBJDIR
1578 # undef TRY_OBJDIRS
1580 if (serverpath) {
1581 /* When looking on the debuginfo server, always just pass the
1582 basename. */
1583 const HChar* basename = debugname;
1584 if (VG_(strstr)(basename, "/") != NULL) {
1585 basename = VG_(strrchr)(basename, '/') + 1;
1587 VG_(sprintf)(debugpath, "%s on %s", basename, serverpath);
1588 dimg = open_debug_file(basename, buildid, crc, rel_ok, serverpath);
1589 if (dimg) goto dimg_ok;
1592 dimg_ok:
1594 ML_(dinfo_free)(objdir);
1597 # if defined(VGO_linux)
1598 if (VG_(clo_enable_debuginfod) && dimg == NULL)
1599 dimg = find_debug_file_debuginfod(objpath, &debugpath, buildid, crc, rel_ok);
1600 # endif
1602 if (dimg != NULL) {
1603 vg_assert(debugpath);
1604 TRACE_SYMTAB("\n");
1605 TRACE_SYMTAB("------ Found a debuginfo file: %s\n", debugpath);
1607 /* Only set once, we might be called again for opening the altfile. */
1608 if (di->fsm.dbgname == NULL)
1609 di->fsm.dbgname = ML_(dinfo_strdup)("di.fdf.4", debugpath);
1612 if (debugpath)
1613 ML_(dinfo_free)(debugpath);
1615 return dimg;
1619 /* Try to find a separate debug file for a given object file, in a
1620 hacky and dangerous way: check only the --extra-debuginfo-path and
1621 the --debuginfo-server. And don't do a consistency check. */
1622 static
1623 DiImage* find_debug_file_ad_hoc( const DebugInfo* di,
1624 const HChar* objpath )
1626 const HChar* extrapath = VG_(clo_extra_debuginfo_path);
1627 const HChar* serverpath = VG_(clo_debuginfo_server);
1629 DiImage* dimg = NULL; /* the img that we found */
1630 HChar* debugpath = NULL; /* where we found it */
1632 HChar *objdir = ML_(dinfo_strdup)("di.fdfah.1", objpath);
1633 HChar *objdirptr;
1635 if ((objdirptr = VG_(strrchr)(objdir, '/')) != NULL)
1636 *objdirptr = '\0';
1638 debugpath = ML_(dinfo_zalloc)(
1639 "di.fdfah.3",
1640 VG_(strlen)(objdir) + 64
1641 + (extrapath ? VG_(strlen)(extrapath) : 0)
1642 + (serverpath ? VG_(strlen)(serverpath) : 0));
1644 if (extrapath) {
1645 VG_(sprintf)(debugpath, "%s/%s", extrapath, objpath);
1646 dimg = ML_(img_from_local_file)(debugpath);
1647 if (dimg != NULL) {
1648 if (VG_(clo_verbosity) > 1) {
1649 VG_(message)(Vg_DebugMsg, " Using (POSSIBLY MISMATCHED) %s\n",
1650 debugpath);
1652 goto dimg_ok;
1655 if (serverpath) {
1656 /* When looking on the debuginfo server, always just pass the
1657 basename. */
1658 const HChar* basename = objpath;
1659 if (VG_(strstr)(basename, "/") != NULL) {
1660 basename = VG_(strrchr)(basename, '/') + 1;
1662 VG_(sprintf)(debugpath, "%s on %s", basename, serverpath);
1663 dimg = ML_(img_from_di_server)(basename, serverpath);
1664 if (dimg != NULL) {
1665 if (VG_(clo_verbosity) > 1) {
1666 VG_(message)(Vg_DebugMsg, " Using (POSSIBLY MISMATCHED) %s\n",
1667 debugpath);
1669 goto dimg_ok;
1673 dimg_ok:
1675 ML_(dinfo_free)(objdir);
1677 if (dimg != NULL) {
1678 vg_assert(debugpath);
1679 TRACE_SYMTAB("\n");
1680 TRACE_SYMTAB("------ Found an ad_hoc debuginfo file: %s\n", debugpath);
1683 if (debugpath)
1684 ML_(dinfo_free)(debugpath);
1686 return dimg;
1690 static DiOffT INDEX_BIS ( DiOffT base, UWord idx, UWord scale ) {
1691 // This is a bit stupid. Really, idx and scale ought to be
1692 // 64-bit quantities, always.
1693 return base + (DiOffT)idx * (DiOffT)scale;
1697 /* Find the file offset corresponding to SVMA by using the program
1698 headers. This is taken from binutils-2.17/binutils/readelf.c
1699 offset_from_vma(). */
1700 static
1701 Word file_offset_from_svma ( /*OUT*/Bool* ok,
1702 Addr svma,
1703 DiImage* img,
1704 DiOffT phdr_ioff,
1705 Word phdr_nent,
1706 Word phdr_ent_szB )
1708 Word i;
1709 for (i = 0; i < phdr_nent; i++) {
1710 ElfXX_Phdr seg;
1711 ML_(img_get)(&seg, img,
1712 INDEX_BIS(phdr_ioff, i, phdr_ent_szB), sizeof(seg));
1713 if (seg.p_type != PT_LOAD)
1714 continue;
1715 if (svma >= (seg.p_vaddr & -seg.p_align)
1716 && svma + 1 <= seg.p_vaddr + seg.p_filesz) {
1717 *ok = True;
1718 return svma - seg.p_vaddr + seg.p_offset;
1721 *ok = False;
1722 return 0;
1725 /* Check if section is compressed and modify DiSlice if it is.
1726 Returns False in case of unsupported compression type.
1728 static Bool check_compression(ElfXX_Shdr* h, DiSlice* s) {
1729 if (h->sh_flags & SHF_COMPRESSED) {
1730 ElfXX_Chdr chdr;
1731 ML_(img_get)(&chdr, s->img, s->ioff, sizeof(ElfXX_Chdr));
1732 if (chdr.ch_type != ELFCOMPRESS_ZLIB)
1733 return False;
1734 s->ioff = ML_(img_mark_compressed_part)(s->img,
1735 s->ioff + sizeof(ElfXX_Chdr),
1736 s->szB - sizeof(ElfXX_Chdr),
1737 (SizeT)chdr.ch_size);
1738 s->szB = chdr.ch_size;
1739 } else if (h->sh_size > SIZE_OF_ZLIB_HEADER) {
1740 /* Read the zlib header. In this case, it should be "ZLIB"
1741 followed by the uncompressed section size, 8 bytes in BE order. */
1742 UChar tmp[SIZE_OF_ZLIB_HEADER];
1743 ML_(img_get)(tmp, s->img, s->ioff, SIZE_OF_ZLIB_HEADER);
1744 if (VG_(memcmp)(tmp, "ZLIB", 4) == 0) {
1745 SizeT size;
1746 # if (VG_WORDSIZE == 8)
1747 size = tmp[4]; size <<= 8;
1748 size += tmp[5]; size <<= 8;
1749 size += tmp[6]; size <<= 8;
1750 size += tmp[7]; size <<= 8;
1751 # else
1752 vg_assert((tmp[4] == 0) && (tmp[5] == 0) && (tmp[6] == 0)
1753 && (tmp[7] == 0));
1754 size = 0;
1755 # endif
1756 size += tmp[8]; size <<= 8;
1757 size += tmp[9]; size <<= 8;
1758 size += tmp[10]; size <<= 8;
1759 size += tmp[11];
1760 s->ioff = ML_(img_mark_compressed_part)(s->img,
1761 s->ioff + SIZE_OF_ZLIB_HEADER,
1762 s->szB - SIZE_OF_ZLIB_HEADER,
1763 size);
1764 s->szB = size;
1767 return True;
1770 /* Helper function to get the readlink path. Returns a copy of path if the
1771 file wasn't a symbolic link. Returns NULL on error. Unless NULL is
1772 returned the result needs to be released with dinfo_free.
1774 static HChar* readlink_path (const HChar *path)
1776 SizeT bufsiz = VG_(strlen)(path);
1777 HChar *buf = ML_(dinfo_strdup)("readlink_path.strdup", path);
1778 UInt tries = 6;
1780 while (tries > 0) {
1781 SysRes res;
1782 #if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
1783 res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD,
1784 (UWord)path, (UWord)buf, bufsiz);
1785 #elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
1786 res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz);
1787 #elif defined(VGO_solaris)
1788 res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD, (UWord)path,
1789 (UWord)buf, bufsiz);
1790 #else
1791 # error Unknown OS
1792 #endif
1793 if (sr_isError(res)) {
1794 if (sr_Err(res) == VKI_EINVAL)
1795 return buf; // It wasn't a symbolic link, return the strdup result.
1796 ML_(dinfo_free)(buf);
1797 return NULL;
1800 SSizeT r = sr_Res(res);
1801 if (r < 0) break;
1802 if (r == bufsiz) { // buffer too small; increase and retry
1803 bufsiz *= 2 + 16;
1804 buf = ML_(dinfo_realloc)("readlink_path.realloc", buf, bufsiz);
1805 tries--;
1806 continue;
1808 buf[r] = '\0';
1809 break;
1812 if (tries == 0) { // We tried, but weird long path?
1813 ML_(dinfo_free)(buf);
1814 return NULL;
1817 if (buf[0] == '/')
1818 return buf;
1820 /* Relative path, add link dir. */
1821 HChar *linkdirptr;
1822 SizeT linkdir_len = VG_(strlen)(path);
1823 if ((linkdirptr = VG_(strrchr)(path, '/')) != NULL)
1824 linkdir_len -= VG_(strlen)(linkdirptr + 1);
1826 SizeT buflen = VG_(strlen)(buf);
1827 SizeT needed = linkdir_len + buflen + 1;
1828 if (bufsiz < needed)
1829 buf = ML_(dinfo_realloc)("readlink_path.linkdir", buf, needed);
1831 VG_(memmove)(buf + linkdir_len, buf, buflen);
1832 VG_(memcpy)(buf, path, linkdir_len);
1833 buf[needed - 1] = '\0';
1835 return buf;
1838 /* The central function for reading ELF debug info. For the
1839 object/exe specified by the DebugInfo, find ELF sections, then read
1840 the symbols, line number info, file name info, CFA (stack-unwind
1841 info) and anything else we want, into the tables within the
1842 supplied DebugInfo.
1845 Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di )
1847 /* This function is long and complex. That, and the presence of
1848 nested scopes, means it's not always easy to see which parts are
1849 in loops/conditionals and which aren't. To make it easier to
1850 follow, points executed exactly once -- that is, those which are
1851 the top level of the function -- are marked TOPLEVEL.
1853 /* Consistent terminology for local variable names, without which
1854 it's almost unfollowably complex:
1856 In which file?
1857 in the main ELF file *_m*
1858 in the debuginfo file *_d*
1859 in the alt debuginfo file *_a*
1861 What kind of thing?
1862 _{m,d,a}img a DiImage*
1863 _{m,d,a}ioff an offset in the image (DiOffT)
1864 _{m,d,a}nent "number of entries"
1865 _{m,d,a}ent_szB "size in bytes of an entry"
1866 ehdr_{m,d,a} ELF header
1867 phdr Program header
1868 shdr Section header
1869 a_X a temporary X
1870 _escn an DiSlice (elf section info) variable
1871 szB size in bytes
1875 /* TOPLEVEL */
1876 Bool res, ok;
1877 Word i, j;
1878 Bool dynbss_present = False;
1879 Bool sdynbss_present = False;
1881 /* Image for the main ELF file we're working with. */
1882 DiImage* mimg = NULL;
1884 /* Ditto for any ELF debuginfo file that we might happen to load. */
1885 DiImage* dimg = NULL;
1887 /* Ditto for alternate ELF debuginfo file that we might happen to load. */
1888 DiImage* aimg = NULL;
1890 /* ELF header offset for the main file. Should be zero since the
1891 ELF header is at start of file. */
1892 DiOffT ehdr_mioff = 0;
1894 /* Program header table image addr, # entries, entry size */
1895 DiOffT phdr_mioff = 0;
1896 UWord phdr_mnent = 0;
1897 UWord phdr_ment_szB = 0;
1899 /* Section header image addr, # entries, entry size. Also the
1900 associated string table. */
1901 DiOffT shdr_mioff = 0;
1902 UWord shdr_mnent = 0;
1903 UWord shdr_ment_szB = 0;
1904 DiOffT shdr_strtab_mioff = 0;
1906 /* SVMAs covered by rx and rw segments and corresponding biases.
1907 Normally each object would provide just one rx and one rw area,
1908 but various ELF mangling tools create objects with multiple
1909 such entries, hence the generality. */
1910 typedef
1911 struct {
1912 Addr svma_base;
1913 Addr svma_limit;
1914 PtrdiffT bias;
1915 Bool exec;
1917 RangeAndBias;
1919 XArray* /* of RangeAndBias */ svma_ranges = NULL;
1921 # if defined(SOLARIS_PT_SUNDWTRACE_THRP)
1922 Addr dtrace_data_vaddr = 0;
1923 # endif
1925 vg_assert(di);
1926 vg_assert(di->fsm.have_rx_map == True);
1927 vg_assert(di->fsm.rw_map_count >= 1);
1928 vg_assert(di->have_dinfo == False);
1929 vg_assert(di->fsm.filename);
1930 vg_assert(!di->symtab);
1931 vg_assert(!di->loctab);
1932 vg_assert(!di->inltab);
1933 vg_assert(!di->cfsi_base);
1934 vg_assert(!di->cfsi_m_ix);
1935 vg_assert(!di->cfsi_rd);
1936 vg_assert(!di->cfsi_exprs);
1937 vg_assert(!di->strpool);
1938 vg_assert(!di->fndnpool);
1939 vg_assert(!di->soname);
1942 Bool has_nonempty_rx = False;
1943 Bool has_nonempty_rw = False;
1944 for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
1945 DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
1946 if (!map->rx && !map->rw)
1947 continue;
1948 if (map->rx && map->size > 0)
1949 has_nonempty_rx = True;
1950 if (map->rw && map->size > 0)
1951 has_nonempty_rw = True;
1952 /* If this doesn't hold true, it means that m_syswrap/m_aspacemgr
1953 managed to do a mapping where the start isn't page aligned.
1954 Which sounds pretty bogus to me. */
1955 vg_assert(VG_IS_PAGE_ALIGNED(map->avma));
1957 vg_assert(has_nonempty_rx);
1958 vg_assert(has_nonempty_rw);
1961 /* ----------------------------------------------------------
1962 At this point, there is very little information in the
1963 DebugInfo. We only know that something that looks like an ELF
1964 file has been mapped rx-ishly and rw-ishly as recorded in the
1965 di->fsm.maps array items. First we examine the file's ELF
1966 Program Header, and, by comparing that against the di->fsm.maps
1967 info, try to figure out the AVMAs for the sections we care
1968 about, that should have been mapped: text, data, sdata, bss,
1969 got, plt, and toc.
1970 ---------------------------------------------------------- */
1972 res = False;
1974 if (VG_(clo_verbosity) > 1 || VG_(clo_trace_redir))
1975 VG_(message)(Vg_DebugMsg, "Reading syms from %s\n",
1976 di->fsm.filename );
1978 /* Connect to the primary object image, so that we can read symbols
1979 and line number info out of it. It will be disconnected
1980 immediately thereafter; it is only connected transiently. */
1981 mimg = ML_(img_from_local_file)(di->fsm.filename);
1982 if (mimg == NULL) {
1983 VG_(message)(Vg_UserMsg, "warning: connection to image %s failed\n",
1984 di->fsm.filename );
1985 VG_(message)(Vg_UserMsg, " no symbols or debug info loaded\n" );
1986 return False;
1989 /* Ok, the object image is available. Now verify that it is a
1990 valid ELF .so or executable image. */
1991 ok = is_elf_object_file_by_DiImage(mimg, False);
1992 if (!ok) {
1993 ML_(symerr)(di, True, "Invalid ELF Header");
1994 goto out;
1997 /* Find where the program and section header tables are, and give
1998 up if either is missing or outside the image (bogus). */
1999 ElfXX_Ehdr ehdr_m;
2000 vg_assert(ehdr_mioff == 0); // ensured by its initialisation
2001 ok = ML_(img_valid)(mimg, ehdr_mioff, sizeof(ehdr_m));
2002 vg_assert(ok); // ML_(is_elf_object_file) should ensure this
2003 ML_(img_get)(&ehdr_m, mimg, ehdr_mioff, sizeof(ehdr_m));
2005 phdr_mioff = ehdr_mioff + ehdr_m.e_phoff;
2006 phdr_mnent = ehdr_m.e_phnum;
2007 phdr_ment_szB = ehdr_m.e_phentsize;
2009 shdr_mioff = ehdr_mioff + ehdr_m.e_shoff;
2010 shdr_mnent = ehdr_m.e_shnum;
2011 shdr_ment_szB = ehdr_m.e_shentsize;
2013 TRACE_SYMTAB("------ Basic facts about the object ------\n");
2014 TRACE_SYMTAB("object: n_oimage %llu\n",
2015 (ULong)ML_(img_size)(mimg));
2016 TRACE_SYMTAB("phdr: ioff %llu nent %lu ent_szB %lu\n",
2017 phdr_mioff, phdr_mnent, phdr_ment_szB);
2018 TRACE_SYMTAB("shdr: ioff %llu nent %lu ent_szB %lu\n",
2019 shdr_mioff, shdr_mnent, shdr_ment_szB);
2020 for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
2021 const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
2022 if (map->rx)
2023 TRACE_SYMTAB("rx_map: avma %#lx size %lu foff %lld\n",
2024 map->avma, map->size, (Long)map->foff);
2026 for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
2027 const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
2028 if (map->rw)
2029 TRACE_SYMTAB("rw_map: avma %#lx size %lu foff %lld\n",
2030 map->avma, map->size, (Long)map->foff);
2033 if (phdr_mnent == 0
2034 || !ML_(img_valid)(mimg, phdr_mioff, phdr_mnent * phdr_ment_szB)) {
2035 ML_(symerr)(di, True, "Missing or invalid ELF Program Header Table");
2036 goto out;
2039 if (shdr_mnent == 0
2040 || !ML_(img_valid)(mimg, shdr_mioff, shdr_mnent * shdr_ment_szB)) {
2041 ML_(symerr)(di, True, "Missing or invalid ELF Section Header Table");
2042 goto out;
2045 /* Also find the section header's string table, and validate. */
2046 /* checked previously by is_elf_object_file: */
2047 vg_assert(ehdr_m.e_shstrndx != SHN_UNDEF);
2049 // shdr_mioff is the offset of the section header table
2050 // and we need the ehdr_m.e_shstrndx'th entry
2051 { ElfXX_Shdr a_shdr;
2052 ML_(img_get)(&a_shdr, mimg,
2053 INDEX_BIS(shdr_mioff, ehdr_m.e_shstrndx, shdr_ment_szB),
2054 sizeof(a_shdr));
2055 shdr_strtab_mioff
2056 = ehdr_mioff /* isn't this always zero? */ + a_shdr.sh_offset;
2058 if (!ML_(img_valid)(mimg, shdr_strtab_mioff,
2059 1/*bogus, but we don't know the real size*/ )) {
2060 ML_(symerr)(di, True, "Invalid ELF Section Header String Table");
2061 goto out;
2065 TRACE_SYMTAB("shdr: string table at %llu\n", shdr_strtab_mioff);
2067 svma_ranges = VG_(newXA)(ML_(dinfo_zalloc), "di.relfdi.1",
2068 ML_(dinfo_free), sizeof(RangeAndBias));
2070 /* TOPLEVEL */
2071 /* Look through the program header table, and:
2072 - copy information from suitable PT_LOAD entries into svma_ranges
2073 - find (or fake up) the .soname for this object.
2075 TRACE_SYMTAB("\n");
2076 TRACE_SYMTAB("------ Examining the program headers ------\n");
2077 vg_assert(di->soname == NULL);
2079 /* TOPLEVEL */
2080 ElfXX_Addr prev_svma = 0;
2082 for (i = 0; i < phdr_mnent; i++) {
2083 ElfXX_Phdr a_phdr;
2084 ML_(img_get)(&a_phdr, mimg,
2085 INDEX_BIS(phdr_mioff, i, phdr_ment_szB),
2086 sizeof(a_phdr));
2088 /* Make sure the PT_LOADable entries are in order and
2089 non-overlapping. This in turn means the address ranges
2090 slurped into svma_ranges are in order and
2091 non-overlapping. */
2093 if (a_phdr.p_type == PT_LOAD) {
2094 TRACE_SYMTAB("PT_LOAD[%ld]: p_vaddr %#lx (prev %#lx)\n",
2095 i, (UWord)a_phdr.p_vaddr, (UWord)prev_svma);
2096 TRACE_SYMTAB("PT_LOAD[%ld]: p_offset %lu, p_filesz %lu,"
2097 " perms %c%c%c\n",
2098 i, (UWord)a_phdr.p_offset, (UWord)a_phdr.p_filesz,
2099 a_phdr.p_flags & PF_R ? 'r' : '-',
2100 a_phdr.p_flags & PF_W ? 'w' : '-',
2101 a_phdr.p_flags & PF_X ? 'x' : '-');
2102 if (a_phdr.p_vaddr < prev_svma) {
2103 ML_(symerr)(di, True,
2104 "ELF Program Headers are not in ascending order");
2105 goto out;
2107 prev_svma = a_phdr.p_vaddr;
2108 if (a_phdr.p_memsz > 0) {
2109 Bool loaded = False;
2110 for (j = 0; j < VG_(sizeXA)(di->fsm.maps); j++) {
2111 const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, j);
2112 if ( (map->rx || map->rw || map->ro)
2113 && map->size > 0 /* stay sane */
2114 && a_phdr.p_offset >= map->foff
2115 && a_phdr.p_offset < map->foff + map->size
2116 && a_phdr.p_offset + a_phdr.p_filesz
2117 <= map->foff + map->size) {
2118 RangeAndBias item;
2119 item.svma_base = a_phdr.p_vaddr;
2120 item.svma_limit = a_phdr.p_vaddr + a_phdr.p_memsz;
2121 item.bias = map->avma - map->foff
2122 + a_phdr.p_offset - a_phdr.p_vaddr;
2123 if (map->rw
2124 && (a_phdr.p_flags & (PF_R | PF_W))
2125 == (PF_R | PF_W)) {
2126 item.exec = False;
2127 VG_(addToXA)(svma_ranges, &item);
2128 TRACE_SYMTAB(
2129 "PT_LOAD[%ld]: acquired as rw, bias 0x%lx\n",
2130 i, (UWord)item.bias);
2131 loaded = True;
2133 if (map->rx
2134 && (a_phdr.p_flags & (PF_R | PF_X))
2135 == (PF_R | PF_X)) {
2136 item.exec = True;
2137 VG_(addToXA)(svma_ranges, &item);
2138 TRACE_SYMTAB(
2139 "PT_LOAD[%ld]: acquired as rx, bias 0x%lx\n",
2140 i, (UWord)item.bias);
2141 loaded = True;
2143 if (map->ro
2144 && (a_phdr.p_flags & (PF_R | PF_W | PF_X))
2145 == PF_R) {
2146 item.exec = False;
2147 VG_(addToXA)(svma_ranges, &item);
2148 TRACE_SYMTAB(
2149 "PT_LOAD[%ld]: acquired as ro, bias 0x%lx\n",
2150 i, (UWord)item.bias);
2151 loaded = True;
2155 if (!loaded) {
2156 # if defined(SOLARIS_PT_SUNDWTRACE_THRP)
2157 if ((a_phdr.p_memsz == VKI_PT_SUNWDTRACE_SIZE)
2158 && ((a_phdr.p_flags & (PF_R | PF_W | PF_X)) == PF_R)) {
2159 TRACE_SYMTAB("PT_LOAD[%ld]: ignore dtrace_data program "
2160 "header\n", i);
2161 dtrace_data_vaddr = a_phdr.p_vaddr;
2162 continue;
2164 # endif /* SOLARIS_PT_SUNDWTRACE_THRP */
2166 ML_(symerr)(di, False,
2167 "ELF section outside all mapped regions");
2168 /* This problem might be solved by further memory mappings.
2169 Avoid the vg_assert(!di->soname) at the beginning of this
2170 function if DYNAMIC section has been already processed. */
2171 if (di->soname) {
2172 ML_(dinfo_free)(di->soname);
2173 di->soname = NULL;
2175 goto out;
2180 /* Try to get the soname. If there isn't one, use "NONE".
2181 The seginfo needs to have some kind of soname in order to
2182 facilitate writing redirect functions, since all redirect
2183 specifications require a soname (pattern). */
2184 if (a_phdr.p_type == PT_DYNAMIC && di->soname == NULL) {
2185 Word stroff = -1;
2186 DiOffT strtab_mioff = DiOffT_INVALID;
2187 for (j = 0; True/*exit check is in the loop*/; j++) {
2188 ElfXX_Dyn t_dyn_m; /* dyn_img[j] */
2189 ML_(img_get)(&t_dyn_m, mimg,
2190 INDEX_BIS(ehdr_mioff + a_phdr.p_offset,
2191 j, sizeof(ElfXX_Dyn)),
2192 sizeof(t_dyn_m));
2193 if (t_dyn_m.d_tag == DT_NULL)
2194 break;
2196 switch (t_dyn_m.d_tag) {
2197 case DT_SONAME: {
2198 stroff = t_dyn_m.d_un.d_val;
2199 break;
2201 case DT_STRTAB: {
2202 Bool ok2 = False;
2203 Word offset = file_offset_from_svma(
2204 &ok2, t_dyn_m.d_un.d_ptr, mimg,
2205 phdr_mioff, phdr_mnent, phdr_ment_szB
2207 if (ok2 && strtab_mioff == DiOffT_INVALID) {
2208 // Check for obviously bogus offsets.
2209 if (!ML_(img_valid)(mimg, offset, 1)) {
2210 ML_(symerr)(di, True, "Invalid DT_STRTAB offset");
2211 goto out;
2213 strtab_mioff = ehdr_mioff + offset;
2214 vg_assert(ehdr_mioff == 0); // should always be
2216 break;
2218 default:
2219 break;
2222 if (stroff != -1 && strtab_mioff != DiOffT_INVALID) {
2223 di->soname = ML_(img_strdup)(mimg, "di.redi.1",
2224 strtab_mioff + stroff);
2225 TRACE_SYMTAB("Found soname = %s\n", di->soname);
2228 } /* for (i = 0; i < phdr_Mnent; i++) ... */
2229 /* TOPLEVEL */
2231 } /* examine the program headers (local scope) */
2233 /* TOPLEVEL */
2235 /* If, after looking at all the program headers, we still didn't
2236 find a soname, add a fake one. */
2237 if (di->soname == NULL) {
2238 TRACE_SYMTAB("No soname found; using (fake) \"NONE\"\n");
2239 di->soname = ML_(dinfo_strdup)("di.redi.2", "NONE");
2242 vg_assert(VG_(sizeXA)(svma_ranges) != 0);
2244 /* Now read the section table. */
2245 TRACE_SYMTAB("\n");
2246 TRACE_SYMTAB("------ Examining the section headers ------\n");
2247 for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
2248 const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
2249 if (map->rx)
2250 TRACE_SYMTAB("rx: at %#lx are mapped foffsets %lld .. %lld\n",
2251 map->avma, (Long)map->foff, (Long)(map->foff + map->size - 1) );
2253 TRACE_SYMTAB("rx: contains these svma regions:\n");
2254 for (i = 0; i < VG_(sizeXA)(svma_ranges); i++) {
2255 const RangeAndBias* reg = VG_(indexXA)(svma_ranges, i);
2256 if (reg->exec)
2257 TRACE_SYMTAB(" svmas %#lx .. %#lx with bias %#lx\n",
2258 reg->svma_base, reg->svma_limit - 1, (UWord)reg->bias );
2260 for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
2261 const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
2262 if (map->rw) {
2263 TRACE_SYMTAB("rw: at %#lx are mapped foffsets %lld .. %lld\n",
2264 map->avma, (Long)map->foff, (Long)(map->foff + map->size - 1) );
2267 TRACE_SYMTAB("rw: contains these svma regions:\n");
2268 for (i = 0; i < VG_(sizeXA)(svma_ranges); i++) {
2269 const RangeAndBias* reg = VG_(indexXA)(svma_ranges, i);
2270 if (!reg->exec)
2271 TRACE_SYMTAB(" svmas %#lx .. %#lx with bias %#lx\n",
2272 reg->svma_base, reg->svma_limit - 1, (UWord)reg->bias );
2275 /* TOPLEVEL */
2276 /* Iterate over section headers */
2277 for (i = 0; i < shdr_mnent; i++) {
2278 ElfXX_Shdr a_shdr;
2279 ML_(img_get)(&a_shdr, mimg,
2280 INDEX_BIS(shdr_mioff, i, shdr_ment_szB), sizeof(a_shdr));
2281 DiOffT name_mioff = shdr_strtab_mioff + a_shdr.sh_name;
2282 HChar* name = ML_(img_strdup)(mimg, "di.redi_name.2", name_mioff);
2283 Addr svma = a_shdr.sh_addr;
2284 OffT foff = a_shdr.sh_offset;
2285 UWord size = a_shdr.sh_size; /* Do not change this to be signed. */
2286 UInt alyn = a_shdr.sh_addralign;
2287 Bool nobits = a_shdr.sh_type == SHT_NOBITS;
2288 /* Look through our collection of info obtained from the PT_LOAD
2289 headers, and make 'inrx' and 'inrw1' point to the first entry
2290 in each that intersects 'avma'. If in each case none is found,
2291 leave the relevant pointer at NULL. */
2292 RangeAndBias* inrx = NULL;
2293 RangeAndBias* inrw1 = NULL;
2294 /* Depending on the link editro there may be two RW PT_LOAD headers
2295 * If so this will point to the seond one */
2296 RangeAndBias* inrw2 = NULL;
2297 /* used to switch between inrw1 and inrw2 */
2298 RangeAndBias* inrw;
2300 for (j = 0; j < VG_(sizeXA)(svma_ranges); j++) {
2301 RangeAndBias* rng = VG_(indexXA)(svma_ranges, j);
2302 if (svma >= rng->svma_base && svma < rng->svma_limit) {
2303 if (!inrx && rng->exec) {
2304 inrx = rng;
2305 } else if (!inrw1 && !rng->exec) {
2306 inrw1 = rng;
2307 } else if (!inrw2 && !rng->exec) {
2308 inrw2 = rng;
2313 TRACE_SYMTAB(" [sec %2ld] %s %s %s al%4u foff %6lld .. %6lld "
2314 " svma %p name \"%s\"\n",
2315 i, inrx ? "rx" : " ", inrw1 ? "rw" : " ", inrw2 ? "rw" : " ",
2316 alyn, (Long) foff, (size == 0) ? (Long)foff : (Long)(foff+size-1),
2317 (void *) svma, name);
2319 /* Check for sane-sized segments. SHT_NOBITS sections have zero
2320 size in the file and their offsets are just conceptual. */
2321 if (!nobits &&
2322 (foff >= ML_(img_size)(mimg) || foff + size > ML_(img_size)(mimg))) {
2323 ML_(symerr)(di, True, "ELF Section extends beyond image end");
2324 goto out;
2327 /* Check for a sane alignment value. */
2328 if (alyn > 0 && -1 == VG_(log2)(alyn)) {
2329 ML_(symerr)(di, True, "ELF Section contains invalid "
2330 ".sh_addralign value");
2331 goto out;
2334 /* Ignore zero sized sections. */
2335 if (size == 0) {
2336 TRACE_SYMTAB("zero sized section \"%s\", ignoring\n", name);
2337 ML_(dinfo_free)(name);
2338 continue;
2341 # define BAD(_secname) \
2342 do { ML_(symerr)(di, True, \
2343 "Can't make sense of " _secname \
2344 " section mapping"); \
2345 /* make sure we don't assert if we find */ \
2346 /* ourselves back in this routine later, */ \
2347 /* with the same di */ \
2348 di->soname = NULL; \
2349 goto out; \
2350 } while (0)
2352 /* Find avma-s for: .text .data .sdata .rodata .bss .sbss .plt .got .opd
2353 and .eh_frame */
2355 /* In inrw2 is non-NULL then it will be used for .data .got.plt .bss */
2357 /* Accept .text where mapped as rx (code), even if zero-sized */
2358 if (0 == VG_(strcmp)(name, ".text")) {
2359 if (inrx && !di->text_present) {
2360 di->text_present = True;
2361 di->text_svma = svma;
2362 di->text_avma = svma + inrx->bias;
2363 di->text_size = size;
2364 di->text_bias = inrx->bias;
2365 di->text_debug_svma = svma;
2366 di->text_debug_bias = inrx->bias;
2367 TRACE_SYMTAB("acquiring .text svma = %#lx .. %#lx\n",
2368 di->text_svma,
2369 di->text_svma + di->text_size - 1);
2370 TRACE_SYMTAB("acquiring .text avma = %#lx .. %#lx\n",
2371 di->text_avma,
2372 di->text_avma + di->text_size - 1);
2373 TRACE_SYMTAB("acquiring .text bias = %#lx\n", (UWord)di->text_bias);
2374 } else {
2375 BAD(".text");
2379 /* Accept .data where mapped as rw (data), even if zero-sized */
2380 if (0 == VG_(strcmp)(name, ".data")) {
2381 # if defined(SOLARIS_PT_SUNDWTRACE_THRP)
2382 if ((size == VKI_PT_SUNWDTRACE_SIZE) && (svma == dtrace_data_vaddr)) {
2383 TRACE_SYMTAB("ignoring .data section for dtrace_data "
2384 "%#lx .. %#lx\n", svma, svma + size - 1);
2385 } else
2386 # endif /* SOLARIS_PT_SUNDWTRACE_THRP */
2388 if (inrw2) {
2389 inrw = inrw2;
2390 } else {
2391 inrw = inrw1;
2394 if (inrw && !di->data_present) {
2395 di->data_present = True;
2396 di->data_svma = svma;
2397 di->data_avma = svma + inrw->bias;
2398 di->data_size = size;
2399 di->data_bias = inrw->bias;
2400 di->data_debug_svma = svma;
2401 di->data_debug_bias = inrw->bias;
2402 TRACE_SYMTAB("acquiring .data svma = %#lx .. %#lx\n",
2403 di->data_svma,
2404 di->data_svma + di->data_size - 1);
2405 TRACE_SYMTAB("acquiring .data avma = %#lx .. %#lx\n",
2406 di->data_avma,
2407 di->data_avma + di->data_size - 1);
2408 TRACE_SYMTAB("acquiring .data bias = %#lx\n", (UWord)di->data_bias);
2409 } else {
2410 BAD(".data");
2414 /* Accept .sdata where mapped as rw (data) */
2415 if (0 == VG_(strcmp)(name, ".sdata")) {
2416 if (inrw1 && !di->sdata_present) {
2417 di->sdata_present = True;
2418 di->sdata_svma = svma;
2419 di->sdata_avma = svma + inrw1->bias;
2420 di->sdata_size = size;
2421 di->sdata_bias = inrw1->bias;
2422 di->sdata_debug_svma = svma;
2423 di->sdata_debug_bias = inrw1->bias;
2424 TRACE_SYMTAB("acquiring .sdata svma = %#lx .. %#lx\n",
2425 di->sdata_svma,
2426 di->sdata_svma + di->sdata_size - 1);
2427 TRACE_SYMTAB("acquiring .sdata avma = %#lx .. %#lx\n",
2428 di->sdata_avma,
2429 di->sdata_avma + di->sdata_size - 1);
2430 TRACE_SYMTAB("acquiring .sdata bias = %#lx\n",
2431 (UWord)di->sdata_bias);
2432 } else {
2433 BAD(".sdata");
2437 /* Accept .rodata where mapped as rx or rw (data), even if zero-sized */
2438 if (0 == VG_(strcmp)(name, ".rodata")) {
2439 if (!di->rodata_present) {
2440 di->rodata_svma = svma;
2441 di->rodata_avma = svma;
2442 di->rodata_size = size;
2443 di->rodata_debug_svma = svma;
2444 if (inrx) {
2445 di->rodata_avma += inrx->bias;
2446 di->rodata_bias = inrx->bias;
2447 di->rodata_debug_bias = inrx->bias;
2448 } else if (inrw1) {
2449 di->rodata_avma += inrw1->bias;
2450 di->rodata_bias = inrw1->bias;
2451 di->rodata_debug_bias = inrw1->bias;
2452 } else {
2453 BAD(".rodata");
2455 di->rodata_present = True;
2456 TRACE_SYMTAB("acquiring .rodata svma = %#lx .. %#lx\n",
2457 di->rodata_svma,
2458 di->rodata_svma + di->rodata_size - 1);
2459 TRACE_SYMTAB("acquiring .rodata avma = %#lx .. %#lx\n",
2460 di->rodata_avma,
2461 di->rodata_avma + di->rodata_size - 1);
2462 TRACE_SYMTAB("acquiring .rodata bias = %#lx\n",
2463 (UWord)di->rodata_bias);
2464 } else {
2465 BAD(".rodata");
2469 if (0 == VG_(strcmp)(name, ".dynbss")) {
2470 if (inrw1 && !di->bss_present) {
2471 dynbss_present = True;
2472 di->bss_present = True;
2473 di->bss_svma = svma;
2474 di->bss_avma = svma + inrw1->bias;
2475 di->bss_size = size;
2476 di->bss_bias = inrw1->bias;
2477 di->bss_debug_svma = svma;
2478 di->bss_debug_bias = inrw1->bias;
2479 TRACE_SYMTAB("acquiring .dynbss svma = %#lx .. %#lx\n",
2480 di->bss_svma,
2481 di->bss_svma + di->bss_size - 1);
2482 TRACE_SYMTAB("acquiring .dynbss avma = %#lx .. %#lx\n",
2483 di->bss_avma,
2484 di->bss_avma + di->bss_size - 1);
2485 TRACE_SYMTAB("acquiring .dynbss bias = %#lx\n",
2486 (UWord)di->bss_bias);
2490 /* Accept .bss where mapped as rw (data), even if zero-sized */
2491 if (0 == VG_(strcmp)(name, ".bss")) {
2493 if (inrw2) {
2494 inrw = inrw2;
2495 } else {
2496 inrw = inrw1;
2499 if (inrw && dynbss_present) {
2500 vg_assert(di->bss_present);
2501 dynbss_present = False;
2502 vg_assert(di->bss_svma + di->bss_size == svma);
2503 di->bss_size += size;
2504 TRACE_SYMTAB("acquiring .bss svma = %#lx .. %#lx\n",
2505 svma, svma + size - 1);
2506 TRACE_SYMTAB("acquiring .bss avma = %#lx .. %#lx\n",
2507 svma + inrw->bias, svma + inrw->bias + size - 1);
2508 TRACE_SYMTAB("acquiring .bss bias = %#lx\n",
2509 (UWord)di->bss_bias);
2510 } else
2512 if (inrw && !di->bss_present) {
2513 di->bss_present = True;
2514 di->bss_svma = svma;
2515 di->bss_avma = svma + inrw->bias;
2516 di->bss_size = size;
2517 di->bss_bias = inrw->bias;
2518 di->bss_debug_svma = svma;
2519 di->bss_debug_bias = inrw->bias;
2520 TRACE_SYMTAB("acquiring .bss svma = %#lx .. %#lx\n",
2521 di->bss_svma,
2522 di->bss_svma + di->bss_size - 1);
2523 TRACE_SYMTAB("acquiring .bss avma = %#lx .. %#lx\n",
2524 di->bss_avma,
2525 di->bss_avma + di->bss_size - 1);
2526 TRACE_SYMTAB("acquiring .bss bias = %#lx\n",
2527 (UWord)di->bss_bias);
2528 } else
2530 /* Now one from the wtf?! department ... */
2531 if (inrx && (!inrw) && !di->bss_present) {
2532 /* File contains a .bss, but it got mapped as rx only.
2533 This is very strange. For now, just pretend we didn't
2534 see it :-) */
2535 di->bss_present = False;
2536 di->bss_svma = 0;
2537 di->bss_avma = 0;
2538 di->bss_size = 0;
2539 di->bss_bias = 0;
2540 di->bss_debug_svma = 0;
2541 di->bss_debug_bias = 0;
2542 if (!VG_(clo_xml)) {
2543 VG_(message)(Vg_UserMsg,
2544 "Warning: the following file's .bss is "
2545 "mapped r-x only - ignoring .bss syms\n");
2546 VG_(message)(Vg_UserMsg, " %s\n", di->fsm.filename
2547 ? di->fsm.filename
2548 : "(null?!)" );
2550 } else
2552 if ((!inrw) && (!inrx) && !di->bss_present) {
2553 /* File contains a .bss, but it didn't get mapped. Ignore. */
2554 di->bss_present = False;
2555 di->bss_svma = 0;
2556 di->bss_avma = 0;
2557 di->bss_size = 0;
2558 di->bss_bias = 0;
2559 } else {
2560 BAD(".bss");
2564 if (0 == VG_(strcmp)(name, ".sdynbss")) {
2565 if (inrw1 && !di->sbss_present) {
2566 sdynbss_present = True;
2567 di->sbss_present = True;
2568 di->sbss_svma = svma;
2569 di->sbss_avma = svma + inrw1->bias;
2570 di->sbss_size = size;
2571 di->sbss_bias = inrw1->bias;
2572 di->sbss_debug_svma = svma;
2573 di->sbss_debug_bias = inrw1->bias;
2574 TRACE_SYMTAB("acquiring .sdynbss svma = %#lx .. %#lx\n",
2575 di->sbss_svma,
2576 di->sbss_svma + di->sbss_size - 1);
2577 TRACE_SYMTAB("acquiring .sdynbss avma = %#lx .. %#lx\n",
2578 di->sbss_avma,
2579 di->sbss_avma + di->sbss_size - 1);
2580 TRACE_SYMTAB("acquiring .sdynbss bias = %#lx\n",
2581 (UWord)di->sbss_bias);
2585 /* Accept .sbss where mapped as rw (data) */
2586 if (0 == VG_(strcmp)(name, ".sbss")) {
2587 if (inrw1 && sdynbss_present) {
2588 vg_assert(di->sbss_present);
2589 sdynbss_present = False;
2590 vg_assert(di->sbss_svma + di->sbss_size == svma);
2591 di->sbss_size += size;
2592 TRACE_SYMTAB("acquiring .sbss svma = %#lx .. %#lx\n",
2593 svma, svma + size - 1);
2594 TRACE_SYMTAB("acquiring .sbss avma = %#lx .. %#lx\n",
2595 svma + inrw1->bias, svma + inrw1->bias + size - 1);
2596 TRACE_SYMTAB("acquiring .sbss bias = %#lx\n", (UWord)di->sbss_bias);
2597 } else
2599 if (inrw1 && !di->sbss_present) {
2600 di->sbss_present = True;
2601 di->sbss_svma = svma;
2602 di->sbss_avma = svma + inrw1->bias;
2603 di->sbss_size = size;
2604 di->sbss_bias = inrw1->bias;
2605 di->sbss_debug_svma = svma;
2606 di->sbss_debug_bias = inrw1->bias;
2607 TRACE_SYMTAB("acquiring .sbss svma = %#lx .. %#lx\n",
2608 di->sbss_svma,
2609 di->sbss_svma + di->sbss_size - 1);
2610 TRACE_SYMTAB("acquiring .sbss avma = %#lx .. %#lx\n",
2611 di->sbss_avma,
2612 di->sbss_avma + di->sbss_size - 1);
2613 TRACE_SYMTAB("acquiring .sbss bias = %#lx\n", (UWord)di->sbss_bias);
2614 } else {
2615 BAD(".sbss");
2619 /* Accept .got where mapped as rw (data) */
2620 if (0 == VG_(strcmp)(name, ".got")) {
2621 if (inrw1 && !di->got_present) {
2622 di->got_present = True;
2623 di->got_avma = svma + inrw1->bias;
2624 di->got_size = size;
2625 TRACE_SYMTAB("acquiring .got avma = %#lx\n", di->got_avma);
2626 } else {
2627 BAD(".got");
2631 /* Accept .got.plt where mapped as rw (data) */
2632 if (0 == VG_(strcmp)(name, ".got.plt")) {
2634 if (inrw2) {
2635 inrw = inrw2;
2636 } else {
2637 inrw = inrw1;
2640 if (inrw && !di->gotplt_present) {
2641 di->gotplt_present = True;
2642 di->gotplt_avma = svma + inrw->bias;
2643 di->gotplt_size = size;
2644 TRACE_SYMTAB("acquiring .got.plt avma = %#lx\n", di->gotplt_avma);
2645 } else if (size != 0) {
2646 BAD(".got.plt");
2650 /* PLT is different on different platforms, it seems. */
2651 # if defined(VGP_x86_linux) || defined(VGP_amd64_linux) \
2652 || defined(VGP_arm_linux) || defined (VGP_s390x_linux) \
2653 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
2654 || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
2655 || defined(VGP_x86_solaris) || defined(VGP_amd64_solaris) \
2656 || defined(VGP_x86_freebsd) || defined(VGP_amd64_freebsd)
2657 /* Accept .plt where mapped as rx (code) */
2658 if (0 == VG_(strcmp)(name, ".plt")) {
2659 if (inrx && !di->plt_present) {
2660 di->plt_present = True;
2661 di->plt_avma = svma + inrx->bias;
2662 di->plt_size = size;
2663 TRACE_SYMTAB("acquiring .plt avma = %#lx\n", di->plt_avma);
2664 } else {
2665 BAD(".plt");
2668 # elif defined(VGP_ppc32_linux)
2669 /* Accept .plt where mapped as rw (data) */
2670 if (0 == VG_(strcmp)(name, ".plt")) {
2671 if (inrw1 && !di->plt_present) {
2672 di->plt_present = True;
2673 di->plt_avma = svma + inrw1->bias;
2674 di->plt_size = size;
2675 TRACE_SYMTAB("acquiring .plt avma = %#lx\n", di->plt_avma);
2676 } else {
2677 BAD(".plt");
2680 # elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
2681 /* Accept .plt where mapped as rw (data), or unmapped */
2682 if (0 == VG_(strcmp)(name, ".plt")) {
2683 if (inrw1 && !di->plt_present) {
2684 di->plt_present = True;
2685 di->plt_avma = svma + inrw1->bias;
2686 di->plt_size = size;
2687 TRACE_SYMTAB("acquiring .plt avma = %#lx\n", di->plt_avma);
2688 } else
2689 if ((!inrw1) && (!inrx) && size > 0 && !di->plt_present) {
2690 /* File contains a .plt, but it didn't get mapped.
2691 Presumably it is not required on this platform. At
2692 least don't reject the situation as invalid. */
2693 di->plt_present = True;
2694 di->plt_avma = 0;
2695 di->plt_size = 0;
2696 } else {
2697 BAD(".plt");
2700 # else
2701 # error "Unsupported platform"
2702 # endif
2704 /* Accept .opd where mapped as rw (data) */
2705 if (0 == VG_(strcmp)(name, ".opd")) {
2706 if (inrw1 && !di->opd_present) {
2707 di->opd_present = True;
2708 di->opd_avma = svma + inrw1->bias;
2709 di->opd_size = size;
2710 TRACE_SYMTAB("acquiring .opd avma = %#lx\n", di->opd_avma);
2711 } else {
2712 BAD(".opd");
2716 /* Accept .eh_frame where mapped as rx (code). This seems to be
2717 the common case. However, if that doesn't pan out, try for
2718 rw (data) instead. We can handle up to N_EHFRAME_SECTS per
2719 ELF object. */
2720 if (0 == VG_(strcmp)(name, ".eh_frame")) {
2721 if (inrx && di->n_ehframe < N_EHFRAME_SECTS) {
2722 di->ehframe_avma[di->n_ehframe] = svma + inrx->bias;
2723 di->ehframe_size[di->n_ehframe] = size;
2724 TRACE_SYMTAB("acquiring .eh_frame avma = %#lx\n",
2725 di->ehframe_avma[di->n_ehframe]);
2726 di->n_ehframe++;
2727 } else
2728 if (inrw1 && di->n_ehframe < N_EHFRAME_SECTS) {
2729 di->ehframe_avma[di->n_ehframe] = svma + inrw1->bias;
2730 di->ehframe_size[di->n_ehframe] = size;
2731 TRACE_SYMTAB("acquiring .eh_frame avma = %#lx\n",
2732 di->ehframe_avma[di->n_ehframe]);
2733 di->n_ehframe++;
2734 } else {
2735 BAD(".eh_frame");
2739 /* Accept .ARM.exidx where mapped as rx (code). */
2740 /* FIXME: make sure the entire section is mapped in, not just
2741 the first address. */
2742 if (0 == VG_(strcmp)(name, ".ARM.exidx")) {
2743 if (inrx && !di->exidx_present) {
2744 di->exidx_present = True;
2745 di->exidx_svma = svma;
2746 di->exidx_avma = svma + inrx->bias;
2747 di->exidx_size = size;
2748 di->exidx_bias = inrx->bias;
2749 TRACE_SYMTAB("acquiring .exidx svma = %#lx .. %#lx\n",
2750 di->exidx_svma,
2751 di->exidx_svma + di->exidx_size - 1);
2752 TRACE_SYMTAB("acquiring .exidx avma = %#lx .. %#lx\n",
2753 di->exidx_avma,
2754 di->exidx_avma + di->exidx_size - 1);
2755 TRACE_SYMTAB("acquiring .exidx bias = %#lx\n",
2756 (UWord)di->exidx_bias);
2757 } else {
2758 BAD(".ARM.exidx");
2762 /* Accept .ARM.extab where mapped as rx (code). */
2763 /* FIXME: make sure the entire section is mapped in, not just
2764 the first address. */
2765 if (0 == VG_(strcmp)(name, ".ARM.extab")) {
2766 if (inrx && !di->extab_present) {
2767 di->extab_present = True;
2768 di->extab_svma = svma;
2769 di->extab_avma = svma + inrx->bias;
2770 di->extab_size = size;
2771 di->extab_bias = inrx->bias;
2772 TRACE_SYMTAB("acquiring .extab svma = %#lx .. %#lx\n",
2773 di->extab_svma,
2774 di->extab_svma + di->extab_size - 1);
2775 TRACE_SYMTAB("acquiring .extab avma = %#lx .. %#lx\n",
2776 di->extab_avma,
2777 di->extab_avma + di->extab_size - 1);
2778 TRACE_SYMTAB("acquiring .extab bias = %#lx\n",
2779 (UWord)di->extab_bias);
2780 } else {
2781 BAD(".ARM.extab");
2785 ML_(dinfo_free)(name);
2787 # undef BAD
2789 } /* iterate over the section headers */
2791 /* TOPLEVEL */
2792 if (0) VG_(printf)("YYYY text_: avma %#lx size %lu bias %#lx\n",
2793 di->text_avma, di->text_size, (UWord)di->text_bias);
2795 if (VG_(clo_verbosity) > 2 || VG_(clo_trace_redir))
2796 VG_(message)(Vg_DebugMsg, " svma %#010lx, avma %#010lx\n",
2797 di->text_avma - di->text_bias,
2798 di->text_avma );
2800 TRACE_SYMTAB("\n");
2801 TRACE_SYMTAB("------ Finding image addresses "
2802 "for debug-info sections ------\n");
2804 /* TOPLEVEL */
2805 /* Find interesting sections, read the symbol table(s), read any
2806 debug information. Each section is located either in the main,
2807 debug or alt-debug files, but only in one. For each section,
2808 |section_escn| records which of |mimg|, |dimg| or |aimg| we
2809 found it in, along with the section's image offset and its size.
2810 The triples (section_img, section_ioff, section_szB) are
2811 consistent, in that they are always either (NULL,
2812 DiOffT_INVALID, 0), or refer to the same image, and are all
2813 assigned together. */
2815 /* TOPLEVEL */
2816 DiSlice strtab_escn = DiSlice_INVALID; // .strtab
2817 DiSlice symtab_escn = DiSlice_INVALID; // .symtab
2818 DiSlice dynstr_escn = DiSlice_INVALID; // .dynstr
2819 DiSlice dynsym_escn = DiSlice_INVALID; // .dynsym
2820 # if defined(VGO_solaris)
2821 DiSlice ldynsym_escn = DiSlice_INVALID; // .SUNW_ldynsym
2822 # endif
2823 DiSlice debuglink_escn = DiSlice_INVALID; // .gnu_debuglink
2824 DiSlice debugaltlink_escn = DiSlice_INVALID; // .gnu_debugaltlink
2825 DiSlice debug_line_escn = DiSlice_INVALID; // .debug_line (dwarf2)
2826 DiSlice debug_info_escn = DiSlice_INVALID; // .debug_info (dwarf2)
2827 DiSlice debug_types_escn = DiSlice_INVALID; // .debug_types (dwarf4)
2828 DiSlice debug_abbv_escn = DiSlice_INVALID; // .debug_abbrev (dwarf2)
2829 DiSlice debug_str_escn = DiSlice_INVALID; // .debug_str (dwarf2)
2830 DiSlice debug_line_str_escn = DiSlice_INVALID; // .debug_line_str(dwarf5)
2831 DiSlice debug_ranges_escn = DiSlice_INVALID; // .debug_ranges (dwarf2)
2832 DiSlice debug_rnglists_escn = DiSlice_INVALID; // .debug_rnglists(dwarf5)
2833 DiSlice debug_loclists_escn = DiSlice_INVALID; // .debug_loclists(dwarf5)
2834 DiSlice debug_addr_escn = DiSlice_INVALID; // .debug_addr (dwarf5)
2835 DiSlice debug_str_offsets_escn = DiSlice_INVALID; // .debug_str_offsets (dwarf5)
2836 DiSlice debug_loc_escn = DiSlice_INVALID; // .debug_loc (dwarf2)
2837 DiSlice debug_frame_escn = DiSlice_INVALID; // .debug_frame (dwarf2)
2838 DiSlice debug_line_alt_escn = DiSlice_INVALID; // .debug_line (alt)
2839 DiSlice debug_info_alt_escn = DiSlice_INVALID; // .debug_info (alt)
2840 DiSlice debug_abbv_alt_escn = DiSlice_INVALID; // .debug_abbrev (alt)
2841 DiSlice debug_str_alt_escn = DiSlice_INVALID; // .debug_str (alt)
2842 DiSlice dwarf1d_escn = DiSlice_INVALID; // .debug (dwarf1)
2843 DiSlice dwarf1l_escn = DiSlice_INVALID; // .line (dwarf1)
2844 DiSlice opd_escn = DiSlice_INVALID; // .opd (dwarf2,
2845 // ppc64be-linux)
2846 DiSlice ehframe_escn[N_EHFRAME_SECTS]; // .eh_frame (dwarf2)
2848 for (i = 0; i < N_EHFRAME_SECTS; i++)
2849 ehframe_escn[i] = DiSlice_INVALID;
2851 /* Find all interesting sections */
2853 UInt ehframe_mix = 0;
2855 /* What FIND does: it finds the section called _SEC_NAME. The
2856 size of it is assigned to _SEC_SIZE. The address of the
2857 section in the transiently loaded oimage is assigned to
2858 _SEC_IMG. If the section is found, _POST_FX is executed
2859 after _SEC_NAME and _SEC_SIZE have been assigned to.
2861 Even for sections which are marked loadable, the client's
2862 ld.so may not have loaded them yet, so there is no guarantee
2863 that we can safely prod around in any such area). Because
2864 the entire object file is transiently mapped aboard for
2865 inspection, it's always safe to inspect that area. */
2867 /* TOPLEVEL */
2868 /* Iterate over section headers (again) */
2869 for (i = 0; i < ehdr_m.e_shnum; i++) {
2871 # define FINDX(_sec_name, _sec_escn, _post_fx) \
2872 do { \
2873 ElfXX_Shdr a_shdr; \
2874 ML_(img_get)(&a_shdr, mimg, \
2875 INDEX_BIS(shdr_mioff, i, shdr_ment_szB), \
2876 sizeof(a_shdr)); \
2877 if (0 == ML_(img_strcmp_c)(mimg, shdr_strtab_mioff \
2878 + a_shdr.sh_name, _sec_name)) { \
2879 Bool nobits; \
2880 _sec_escn.img = mimg; \
2881 _sec_escn.ioff = (DiOffT)a_shdr.sh_offset; \
2882 _sec_escn.szB = a_shdr.sh_size; \
2883 if (!check_compression(&a_shdr, &_sec_escn)) { \
2884 ML_(symerr)(di, True, " Compression type is unsupported"); \
2885 goto out; \
2887 nobits = a_shdr.sh_type == SHT_NOBITS; \
2888 vg_assert(_sec_escn.img != NULL); \
2889 vg_assert(_sec_escn.ioff != DiOffT_INVALID); \
2890 TRACE_SYMTAB( "%-18s: ioff %llu .. %llu\n", \
2891 _sec_name, (ULong)a_shdr.sh_offset, \
2892 ((ULong)a_shdr.sh_offset) + a_shdr.sh_size - 1); \
2893 /* SHT_NOBITS sections have zero size in the file. */ \
2894 if (!nobits && \
2895 a_shdr.sh_offset + \
2896 a_shdr.sh_size > ML_(img_real_size)(mimg)) { \
2897 ML_(symerr)(di, True, \
2898 " section beyond image end?!"); \
2899 goto out; \
2901 _post_fx; \
2903 } while (0);
2905 /* Version with no post-effects */
2906 # define FIND(_sec_name, _sec_escn) \
2907 FINDX(_sec_name, _sec_escn, /**/)
2909 /* NAME ElfSec */
2910 FIND( ".dynsym", dynsym_escn)
2911 FIND( ".dynstr", dynstr_escn)
2912 FIND( ".symtab", symtab_escn)
2913 FIND( ".strtab", strtab_escn)
2914 # if defined(VGO_solaris)
2915 FIND( ".SUNW_ldynsym", ldynsym_escn)
2916 # endif
2918 FIND( ".gnu_debuglink", debuglink_escn)
2919 FIND( ".gnu_debugaltlink", debugaltlink_escn)
2921 FIND( ".debug_line", debug_line_escn)
2922 if (!ML_(sli_is_valid)(debug_line_escn))
2923 FIND(".zdebug_line", debug_line_escn)
2925 FIND( ".debug_info", debug_info_escn)
2926 if (!ML_(sli_is_valid)(debug_info_escn))
2927 FIND(".zdebug_info", debug_info_escn)
2929 FIND( ".debug_types", debug_types_escn)
2930 if (!ML_(sli_is_valid)(debug_types_escn))
2931 FIND(".zdebug_types", debug_types_escn)
2933 FIND( ".debug_abbrev", debug_abbv_escn)
2934 if (!ML_(sli_is_valid)(debug_abbv_escn))
2935 FIND(".zdebug_abbrev", debug_abbv_escn)
2937 FIND( ".debug_str", debug_str_escn)
2938 if (!ML_(sli_is_valid)(debug_str_escn))
2939 FIND(".zdebug_str", debug_str_escn)
2941 FIND( ".debug_line_str", debug_line_str_escn)
2942 if (!ML_(sli_is_valid)(debug_line_str_escn))
2943 FIND(".zdebug_str", debug_line_str_escn)
2945 FIND( ".debug_ranges", debug_ranges_escn)
2946 if (!ML_(sli_is_valid)(debug_ranges_escn))
2947 FIND(".zdebug_ranges", debug_ranges_escn)
2949 FIND( ".debug_rnglists", debug_rnglists_escn)
2950 if (!ML_(sli_is_valid)(debug_rnglists_escn))
2951 FIND(".zdebug_rnglists", debug_rnglists_escn)
2953 FIND( ".debug_loclists", debug_loclists_escn)
2954 if (!ML_(sli_is_valid)(debug_loclists_escn))
2955 FIND(".zdebug_loclists", debug_loclists_escn)
2957 FIND( ".debug_loc", debug_loc_escn)
2958 if (!ML_(sli_is_valid)(debug_loc_escn))
2959 FIND(".zdebug_loc", debug_loc_escn)
2961 FIND( ".debug_frame", debug_frame_escn)
2962 if (!ML_(sli_is_valid)(debug_frame_escn))
2963 FIND(".zdebug_frame", debug_frame_escn)
2965 FIND( ".debug_addr", debug_addr_escn)
2966 if (!ML_(sli_is_valid)(debug_addr_escn))
2967 FIND(".zdebug_addr", debug_addr_escn)
2969 FIND( ".debug_str_offsets", debug_str_offsets_escn)
2970 if (!ML_(sli_is_valid)(debug_str_offsets_escn))
2971 FIND(".zdebug_str_offsets", debug_str_offsets_escn)
2973 FIND( ".debug", dwarf1d_escn)
2974 FIND( ".line", dwarf1l_escn)
2976 FIND( ".opd", opd_escn)
2978 FINDX( ".eh_frame", ehframe_escn[ehframe_mix],
2979 do { ehframe_mix++; vg_assert(ehframe_mix <= N_EHFRAME_SECTS);
2980 } while (0)
2982 /* Comment_on_EH_FRAME_MULTIPLE_INSTANCES: w.r.t. .eh_frame
2983 multi-instance kludgery, how are we assured that the order
2984 in which we fill in ehframe_escn[] is consistent with the
2985 order in which we previously filled in di->ehframe_avma[]
2986 and di->ehframe_size[] ? By the fact that in both cases,
2987 these arrays were filled in by iterating over the section
2988 headers top-to-bottom. So both loops (this one and the
2989 previous one) encounter the .eh_frame entries in the same
2990 order and so fill in these arrays in a consistent order.
2993 # undef FINDX
2994 # undef FIND
2995 } /* Iterate over section headers (again) */
2997 /* TOPLEVEL */
2998 /* Now, see if we can find a debuginfo object, and if so connect
2999 |dimg| to it. */
3000 vg_assert(dimg == NULL && aimg == NULL);
3002 #if defined(VGO_freebsd)
3003 /* */
3004 read_and_set_osrel(mimg);
3006 #endif
3008 /* Look for a build-id */
3009 HChar* buildid = find_buildid(mimg, False, False);
3011 /* If we don't have a .debug_info section in the main image then
3012 look for a debug image that matches either the build-id or
3013 the debuglink-CRC32 in the main image. If the main image
3014 doesn't contain either of those then this won't even bother
3015 to try looking. This looks in all known places, including
3016 the --extra-debuginfo-path if specified and on the
3017 --debuginfo-server if specified. */
3018 if (debug_info_escn.img == NULL &&
3019 (buildid != NULL || debuglink_escn.img != NULL)) {
3020 /* Do have a debuglink section? */
3021 if (debuglink_escn.img != NULL) {
3022 UInt crc_offset
3023 = VG_ROUNDUP(ML_(img_strlen)(debuglink_escn.img,
3024 debuglink_escn.ioff)+1, 4);
3025 vg_assert(crc_offset + sizeof(UInt) <= debuglink_escn.szB);
3027 /* Extract the CRC from the debuglink section */
3028 UInt crc = ML_(img_get_UInt)(debuglink_escn.img,
3029 debuglink_escn.ioff + crc_offset);
3031 /* See if we can find a matching debug file */
3032 HChar* debuglink_str_m
3033 = ML_(img_strdup)(debuglink_escn.img,
3034 "di.redi_dlk.1", debuglink_escn.ioff);
3035 dimg = find_debug_file( di, di->fsm.filename, buildid,
3036 debuglink_str_m, crc, False );
3037 if (debuglink_str_m)
3038 ML_(dinfo_free)(debuglink_str_m);
3039 } else {
3040 /* See if we can find a matching debug file */
3041 dimg = find_debug_file( di, di->fsm.filename, buildid,
3042 NULL, 0, False );
3046 if (buildid) {
3047 ML_(dinfo_free)(buildid);
3048 buildid = NULL; /* paranoia */
3051 /* As a last-ditch measure, try looking for in the
3052 --extra-debuginfo-path and/or on the --debuginfo-server, but
3053 only in the case where --allow-mismatched-debuginfo=yes.
3054 This is dangerous in that (1) it gives no assurance that the
3055 debuginfo object matches the main one, and hence (2) we will
3056 very likely get an assertion in the code below, if indeed
3057 there is a mismatch. Hence it is disabled by default
3058 (--allow-mismatched-debuginfo=no). Nevertheless it's
3059 sometimes a useful way of getting out of a tight spot.
3061 Note that we're ignoring the name in the .gnu_debuglink
3062 section here, and just looking for a file of the same name
3063 either the extra-path or on the server. */
3064 if (dimg == NULL && VG_(clo_allow_mismatched_debuginfo)) {
3065 dimg = find_debug_file_ad_hoc( di, di->fsm.filename );
3068 /* TOPLEVEL */
3069 /* If we were successful in finding a debug image, pull various
3070 SVMA/bias/size and image addresses out of it. */
3071 if (dimg != NULL && is_elf_object_file_by_DiImage(dimg, False)) {
3073 /* Pull out and validate program header and section header info */
3074 DiOffT ehdr_dioff = 0;
3075 ElfXX_Ehdr ehdr_dimg;
3076 ML_(img_get)(&ehdr_dimg, dimg, ehdr_dioff, sizeof(ehdr_dimg));
3078 DiOffT phdr_dioff = ehdr_dimg.e_phoff;
3079 UWord phdr_dnent = ehdr_dimg.e_phnum;
3080 UWord phdr_dent_szB = ehdr_dimg.e_phentsize;
3082 DiOffT shdr_dioff = ehdr_dimg.e_shoff;
3083 UWord shdr_dnent = ehdr_dimg.e_shnum;
3084 UWord shdr_dent_szB = ehdr_dimg.e_shentsize;
3086 DiOffT shdr_strtab_dioff = DiOffT_INVALID;
3088 /* SVMAs covered by rx and rw segments and corresponding bias. */
3089 Addr rx_dsvma_limit = 0;
3090 PtrdiffT rx_dbias = 0;
3091 Addr rw_dsvma_limit = 0;
3092 PtrdiffT rw_dbias = 0;
3094 Bool need_symtab, need_dwarf2, need_dwarf1;
3096 if (phdr_dnent == 0
3097 || !ML_(img_valid)(dimg, phdr_dioff,
3098 phdr_dnent * phdr_dent_szB)) {
3099 ML_(symerr)(di, True,
3100 "Missing or invalid ELF Program Header Table"
3101 " (debuginfo file)");
3102 goto out;
3105 if (shdr_dnent == 0
3106 || !ML_(img_valid)(dimg, shdr_dioff,
3107 shdr_dnent * shdr_dent_szB)) {
3108 ML_(symerr)(di, True,
3109 "Missing or invalid ELF Section Header Table"
3110 " (debuginfo file)");
3111 goto out;
3114 /* Also find the section header's string table, and validate. */
3115 /* checked previously by is_elf_object_file: */
3116 vg_assert(ehdr_dimg.e_shstrndx != SHN_UNDEF);
3118 // shdr_dioff is the offset of the section header table
3119 // and we need the ehdr_dimg.e_shstrndx'th entry
3120 { ElfXX_Shdr a_shdr;
3121 ML_(img_get)(&a_shdr, dimg,
3122 INDEX_BIS(shdr_dioff, ehdr_dimg.e_shstrndx,
3123 shdr_dent_szB),
3124 sizeof(a_shdr));
3125 shdr_strtab_dioff = a_shdr.sh_offset;
3126 if (!ML_(img_valid)(dimg, shdr_strtab_dioff,
3127 1/*bogus, but we don't know the real size*/)) {
3128 ML_(symerr)(di, True,
3129 "Invalid ELF Section Header String Table"
3130 " (debuginfo file)");
3131 goto out;
3135 for (i = 0; i < ehdr_dimg.e_phnum; i++) {
3136 ElfXX_Phdr a_phdr;
3137 ML_(img_get)(&a_phdr, dimg, INDEX_BIS(ehdr_dimg.e_phoff,
3138 i, phdr_dent_szB),
3139 sizeof(a_phdr));
3140 if (a_phdr.p_type == PT_LOAD) {
3141 for (j = 0; j < VG_(sizeXA)(di->fsm.maps); j++) {
3142 const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, j);
3143 if ( a_phdr.p_offset >= map->foff
3144 && a_phdr.p_offset < map->foff + map->size
3145 && a_phdr.p_offset + a_phdr.p_filesz
3146 < map->foff + map->size) {
3147 if (map->rx && rx_dsvma_limit == 0) {
3148 rx_dsvma_limit = a_phdr.p_vaddr + a_phdr.p_memsz;
3149 rx_dbias = map->avma - map->foff + a_phdr.p_offset
3150 - a_phdr.p_vaddr;
3152 if (map->rw && rw_dsvma_limit == 0) {
3153 rw_dsvma_limit = a_phdr.p_vaddr + a_phdr.p_memsz;
3154 rw_dbias = map->avma - map->foff + a_phdr.p_offset
3155 - a_phdr.p_vaddr;
3157 break;
3163 need_symtab = (symtab_escn.img == NULL);
3164 need_dwarf2 = (debug_info_escn.img == NULL);
3165 need_dwarf1 = (dwarf1d_escn.img == NULL);
3167 /* Find all interesting sections in the debug image */
3168 for (i = 0; i < ehdr_dimg.e_shnum; i++) {
3170 /* Find debug svma and bias information for sections
3171 we found in the main file. */
3173 # define FIND(_sec, _seg) \
3174 do { \
3175 ElfXX_Shdr a_shdr; \
3176 ML_(img_get)(&a_shdr, dimg, \
3177 INDEX_BIS(shdr_dioff, i, shdr_dent_szB), \
3178 sizeof(a_shdr)); \
3179 if (di->_sec##_present \
3180 && 0 == ML_(img_strcmp_c)(dimg, shdr_strtab_dioff \
3181 + a_shdr.sh_name, "." #_sec)) { \
3182 vg_assert(di->_sec##_size == a_shdr.sh_size); \
3183 /* JRS 2013-Jun-01: the following assert doesn't contain */ \
3184 /* any ==s, which seems to me to be suspicious. */ \
3185 vg_assert(di->_sec##_avma + a_shdr.sh_addr + _seg##_dbias); \
3186 /* Assume we have a correct value for the main */ \
3187 /* object's bias. Use that to derive the debuginfo */ \
3188 /* object's bias, by adding the difference in SVMAs */ \
3189 /* for the corresponding sections in the two files. */ \
3190 /* That should take care of all prelinking effects. */ \
3191 di->_sec##_debug_svma = a_shdr.sh_addr; \
3192 di->_sec##_debug_bias \
3193 = di->_sec##_bias + \
3194 di->_sec##_svma - di->_sec##_debug_svma; \
3195 TRACE_SYMTAB("acquiring ." #_sec \
3196 " debug svma = %#lx .. %#lx\n", \
3197 di->_sec##_debug_svma, \
3198 di->_sec##_debug_svma + di->_sec##_size - 1); \
3199 TRACE_SYMTAB("acquiring ." #_sec " debug bias = %#lx\n", \
3200 (UWord)di->_sec##_debug_bias); \
3202 } while (0);
3204 /* SECTION SEGMENT */
3205 FIND(text, rx)
3206 FIND(data, rw)
3207 FIND(sdata, rw)
3208 FIND(rodata, rw)
3209 FIND(bss, rw)
3210 FIND(sbss, rw)
3212 # undef FIND
3214 /* Same deal as previous FIND, except only do it for those
3215 sections which we didn't find in the main file. */
3217 # define FIND(_condition, _sec_name, _sec_escn) \
3218 do { \
3219 ElfXX_Shdr a_shdr; \
3220 ML_(img_get)(&a_shdr, dimg, \
3221 INDEX_BIS(shdr_dioff, i, shdr_dent_szB), \
3222 sizeof(a_shdr)); \
3223 if (_condition \
3224 && 0 == ML_(img_strcmp_c)(dimg, shdr_strtab_dioff \
3225 + a_shdr.sh_name, _sec_name)) { \
3226 Bool nobits; \
3227 if (_sec_escn.img != NULL) { \
3228 ML_(symerr)(di, True, \
3229 " debuginfo section duplicates a" \
3230 " section in the main ELF file"); \
3231 goto out; \
3233 _sec_escn.img = dimg; \
3234 _sec_escn.ioff = (DiOffT)a_shdr.sh_offset; \
3235 _sec_escn.szB = a_shdr.sh_size; \
3236 if (!check_compression(&a_shdr, &_sec_escn)) { \
3237 ML_(symerr)(di, True, " Compression type is unsupported"); \
3238 goto out; \
3240 nobits = a_shdr.sh_type == SHT_NOBITS; \
3241 vg_assert(_sec_escn.img != NULL); \
3242 vg_assert(_sec_escn.ioff != DiOffT_INVALID); \
3243 TRACE_SYMTAB( "%-18s: dioff %llu .. %llu\n", \
3244 _sec_name, \
3245 (ULong)a_shdr.sh_offset, \
3246 ((ULong)a_shdr.sh_offset) + a_shdr.sh_size - 1); \
3247 /* SHT_NOBITS sections have zero size in the file. */ \
3248 if (!nobits && a_shdr.sh_offset \
3249 + a_shdr.sh_size > ML_(img_real_size)(_sec_escn.img)) { \
3250 ML_(symerr)(di, True, \
3251 " section beyond image end?!"); \
3252 goto out; \
3255 } while (0);
3257 /* NEEDED? NAME ElfSec */
3258 FIND( need_symtab, ".symtab", symtab_escn)
3259 FIND( need_symtab, ".strtab", strtab_escn)
3260 FIND( need_dwarf2, ".debug_line", debug_line_escn)
3261 if (!ML_(sli_is_valid)(debug_line_escn))
3262 FIND(need_dwarf2, ".zdebug_line", debug_line_escn)
3264 FIND( need_dwarf2, ".debug_info", debug_info_escn)
3265 if (!ML_(sli_is_valid)(debug_info_escn))
3266 FIND(need_dwarf2, ".zdebug_info", debug_info_escn)
3268 FIND( need_dwarf2, ".debug_types", debug_types_escn)
3269 if (!ML_(sli_is_valid)(debug_types_escn))
3270 FIND(need_dwarf2, ".zdebug_types", debug_types_escn)
3272 FIND( need_dwarf2, ".debug_abbrev", debug_abbv_escn)
3273 if (!ML_(sli_is_valid)(debug_abbv_escn))
3274 FIND(need_dwarf2, ".zdebug_abbrev", debug_abbv_escn)
3276 FIND( need_dwarf2, ".debug_str", debug_str_escn)
3277 if (!ML_(sli_is_valid)(debug_str_escn))
3278 FIND(need_dwarf2, ".zdebug_str", debug_str_escn)
3280 FIND( need_dwarf2, ".debug_line_str", debug_line_str_escn)
3281 if (!ML_(sli_is_valid)(debug_line_str_escn))
3282 FIND(need_dwarf2, ".zdebug_line_str", debug_line_str_escn)
3284 FIND( need_dwarf2, ".debug_ranges", debug_ranges_escn)
3285 if (!ML_(sli_is_valid)(debug_ranges_escn))
3286 FIND(need_dwarf2, ".zdebug_ranges", debug_ranges_escn)
3288 FIND( need_dwarf2, ".debug_rnglists", debug_rnglists_escn)
3289 if (!ML_(sli_is_valid)(debug_rnglists_escn))
3290 FIND(need_dwarf2, ".zdebug_rnglists", debug_rnglists_escn)
3292 FIND( need_dwarf2, ".debug_loclists", debug_loclists_escn)
3293 if (!ML_(sli_is_valid)(debug_loclists_escn))
3294 FIND(need_dwarf2, ".zdebug_loclists", debug_loclists_escn)
3296 FIND( need_dwarf2, ".debug_loc", debug_loc_escn)
3297 if (!ML_(sli_is_valid)(debug_loc_escn))
3298 FIND(need_dwarf2, ".zdebug_loc", debug_loc_escn)
3300 FIND( need_dwarf2, ".debug_frame", debug_frame_escn)
3301 if (!ML_(sli_is_valid)(debug_frame_escn))
3302 FIND(need_dwarf2, ".zdebug_frame", debug_frame_escn)
3304 FIND( need_dwarf2, ".debug_addr", debug_addr_escn)
3305 if (!ML_(sli_is_valid)(debug_addr_escn))
3306 FIND(need_dwarf2, ".zdebug_addr", debug_addr_escn)
3308 FIND( need_dwarf2, ".debug_str_offsets", debug_str_offsets_escn)
3309 if (!ML_(sli_is_valid)(debug_str_offsets_escn))
3310 FIND(need_dwarf2, ".zdebug_str_offsets", debug_str_offsets_escn)
3312 if (!ML_(sli_is_valid)(debugaltlink_escn))
3313 FIND( need_dwarf2, ".gnu_debugaltlink", debugaltlink_escn)
3315 FIND( need_dwarf1, ".debug", dwarf1d_escn)
3316 FIND( need_dwarf1, ".line", dwarf1l_escn)
3318 # undef FIND
3319 } /* Find all interesting sections */
3320 } /* do we have a debug image? */
3322 /* TOPLEVEL */
3323 /* Look for alternate debug image, and if found, connect |aimg|
3324 to it. */
3325 vg_assert(aimg == NULL);
3327 if (debugaltlink_escn.img != NULL) {
3328 HChar* altfile_str_m
3329 = ML_(img_strdup)(debugaltlink_escn.img,
3330 "di.fbi.3", debugaltlink_escn.ioff);
3331 UInt buildid_offset = ML_(img_strlen)(debugaltlink_escn.img,
3332 debugaltlink_escn.ioff)+1;
3334 vg_assert(buildid_offset < debugaltlink_escn.szB);
3336 HChar *altbuildid
3337 = ML_(dinfo_zalloc)("di.fbi.4",
3338 (debugaltlink_escn.szB - buildid_offset)
3339 * 2 + 1);
3341 /* The altfile might be relative to the debug file or main file.
3342 Make sure that we got the real file, not a symlink. */
3343 HChar *dbgname = di->fsm.dbgname ? di->fsm.dbgname : di->fsm.filename;
3344 HChar* rdbgname = readlink_path (dbgname);
3345 if (rdbgname == NULL)
3346 rdbgname = ML_(dinfo_strdup)("rdbgname", dbgname);
3348 for (j = 0; j < debugaltlink_escn.szB - buildid_offset; j++)
3349 VG_(sprintf)(
3350 altbuildid + 2 * j, "%02x",
3351 (UInt)ML_(img_get_UChar)(debugaltlink_escn.img,
3352 debugaltlink_escn.ioff
3353 + buildid_offset + j));
3355 /* See if we can find a matching debug file */
3356 aimg = find_debug_file( di, rdbgname, altbuildid,
3357 altfile_str_m, 0, True );
3359 ML_(dinfo_free)(rdbgname);
3361 if (altfile_str_m)
3362 ML_(dinfo_free)(altfile_str_m);
3363 ML_(dinfo_free)(altbuildid);
3366 /* TOPLEVEL */
3367 /* If we were successful in finding alternate debug image, pull various
3368 size and image addresses out of it. */
3369 if (aimg != NULL && is_elf_object_file_by_DiImage(aimg, True)) {
3371 /* Pull out and validate program header and section header info */
3372 DiOffT ehdr_aioff = 0;
3373 ElfXX_Ehdr ehdr_aimg;
3374 ML_(img_get)(&ehdr_aimg, aimg, ehdr_aioff, sizeof(ehdr_aimg));
3376 DiOffT shdr_aioff = ehdr_aimg.e_shoff;
3377 UWord shdr_anent = ehdr_aimg.e_shnum;
3378 UWord shdr_aent_szB = ehdr_aimg.e_shentsize;
3380 DiOffT shdr_strtab_aioff = DiOffT_INVALID;
3382 if (shdr_anent == 0
3383 || !ML_(img_valid)(aimg, shdr_aioff,
3384 shdr_anent * shdr_aent_szB)) {
3385 ML_(symerr)(di, True,
3386 "Missing or invalid ELF Section Header Table"
3387 " (alternate debuginfo file)");
3388 goto out;
3391 /* Also find the section header's string table, and validate. */
3392 /* checked previously by is_elf_object_file: */
3393 vg_assert(ehdr_aimg.e_shstrndx != SHN_UNDEF);
3395 // shdr_aioff is the offset of the section header table
3396 // and we need the ehdr_aimg.e_shstrndx'th entry
3397 { ElfXX_Shdr a_shdr;
3398 ML_(img_get)(&a_shdr, aimg,
3399 INDEX_BIS(shdr_aioff, ehdr_aimg.e_shstrndx,
3400 shdr_aent_szB),
3401 sizeof(a_shdr));
3402 shdr_strtab_aioff = a_shdr.sh_offset;
3403 if (!ML_(img_valid)(aimg, shdr_strtab_aioff,
3404 1/*bogus, but we don't know the real size*/)) {
3405 ML_(symerr)(di, True,
3406 "Invalid ELF Section Header String Table"
3407 " (alternate debuginfo file)");
3408 goto out;
3412 /* Find all interesting sections */
3413 for (i = 0; i < ehdr_aimg.e_shnum; i++) {
3415 # define FIND(_sec_name, _sec_escn) \
3416 do { \
3417 ElfXX_Shdr a_shdr; \
3418 ML_(img_get)(&a_shdr, aimg, \
3419 INDEX_BIS(shdr_aioff, i, shdr_aent_szB), \
3420 sizeof(a_shdr)); \
3421 if (0 == ML_(img_strcmp_c)(aimg, shdr_strtab_aioff \
3422 + a_shdr.sh_name, _sec_name)) { \
3423 if (_sec_escn.img != NULL) { \
3424 ML_(symerr)(di, True, \
3425 " alternate debuginfo section duplicates a" \
3426 " section in the main ELF file"); \
3427 goto out; \
3429 _sec_escn.img = aimg; \
3430 _sec_escn.ioff = (DiOffT)a_shdr.sh_offset; \
3431 _sec_escn.szB = a_shdr.sh_size; \
3432 if (!check_compression(&a_shdr, &_sec_escn)) { \
3433 ML_(symerr)(di, True, " Compression type is " \
3434 "unsupported"); \
3435 goto out; \
3437 vg_assert(_sec_escn.img != NULL); \
3438 vg_assert(_sec_escn.ioff != DiOffT_INVALID); \
3439 TRACE_SYMTAB( "%-18s: aioff %llu .. %llu\n", \
3440 _sec_name, \
3441 (ULong)a_shdr.sh_offset, \
3442 ((ULong)a_shdr.sh_offset) + a_shdr.sh_size - 1); \
3444 } while (0);
3446 /* NAME ElfSec */
3447 FIND(".debug_line", debug_line_alt_escn)
3448 if (!ML_(sli_is_valid)(debug_line_alt_escn))
3449 FIND(".zdebug_line", debug_line_alt_escn)
3451 FIND(".debug_info", debug_info_alt_escn)
3452 if (!ML_(sli_is_valid)(debug_info_alt_escn))
3453 FIND(".zdebug_info", debug_info_alt_escn)
3455 FIND(".debug_abbrev", debug_abbv_alt_escn)
3456 if (!ML_(sli_is_valid)(debug_abbv_alt_escn))
3457 FIND(".zdebug_abbrev", debug_abbv_alt_escn)
3459 FIND(".debug_str", debug_str_alt_escn)
3460 if (!ML_(sli_is_valid)(debug_str_alt_escn))
3461 FIND(".zdebug_str", debug_str_alt_escn)
3463 # undef FIND
3464 } /* Find all interesting sections */
3465 } /* do we have a debug image? */
3468 /* TOPLEVEL */
3469 /* Check some sizes */
3470 vg_assert((dynsym_escn.szB % sizeof(ElfXX_Sym)) == 0);
3471 vg_assert((symtab_escn.szB % sizeof(ElfXX_Sym)) == 0);
3472 # if defined(VGO_solaris)
3473 vg_assert((ldynsym_escn.szB % sizeof(ElfXX_Sym)) == 0);
3474 # endif
3476 /* TOPLEVEL */
3477 /* Read symbols */
3479 void (*read_elf_symtab)(struct _DebugInfo*, const HChar*,
3480 DiSlice*, DiSlice*, DiSlice*, Bool);
3481 Bool symtab_in_debug;
3482 # if defined(VGP_ppc64be_linux)
3483 read_elf_symtab = read_elf_symtab__ppc64be_linux;
3484 # else
3485 read_elf_symtab = read_elf_symtab__normal;
3486 # endif
3487 symtab_in_debug = symtab_escn.img == dimg;
3488 read_elf_symtab(di, "symbol table",
3489 &symtab_escn, &strtab_escn, &opd_escn,
3490 symtab_in_debug);
3491 read_elf_symtab(di, "dynamic symbol table",
3492 &dynsym_escn, &dynstr_escn, &opd_escn,
3493 False);
3494 # if defined(VGO_solaris)
3495 read_elf_symtab(di, "local dynamic symbol table",
3496 &ldynsym_escn, &dynstr_escn, &opd_escn,
3497 False);
3498 # endif
3501 /* TOPLEVEL */
3502 /* Read .eh_frame and .debug_frame (call-frame-info) if any. Do
3503 the .eh_frame section(s) first. */
3504 vg_assert(di->n_ehframe >= 0 && di->n_ehframe <= N_EHFRAME_SECTS);
3505 for (i = 0; i < di->n_ehframe; i++) {
3506 /* see Comment_on_EH_FRAME_MULTIPLE_INSTANCES above for why
3507 this next assertion should hold. */
3508 vg_assert(ML_(sli_is_valid)(ehframe_escn[i]));
3509 vg_assert(ehframe_escn[i].szB == di->ehframe_size[i]);
3510 ML_(read_callframe_info_dwarf3)( di,
3511 ehframe_escn[i],
3512 di->ehframe_avma[i],
3513 True/*is_ehframe*/ );
3515 if (ML_(sli_is_valid)(debug_frame_escn)) {
3516 ML_(read_callframe_info_dwarf3)( di,
3517 debug_frame_escn,
3518 0/*assume zero avma*/,
3519 False/*!is_ehframe*/ );
3522 /* TOPLEVEL */
3523 /* jrs 2006-01-01: icc-8.1 has been observed to generate
3524 binaries without debug_str sections. Don't preclude
3525 debuginfo reading for that reason, but, in
3526 read_unitinfo_dwarf2, do check that debugstr is non-NULL
3527 before using it. */
3528 if (ML_(sli_is_valid)(debug_info_escn)
3529 && ML_(sli_is_valid)(debug_abbv_escn)
3530 && ML_(sli_is_valid)(debug_line_escn)) {
3531 /* The old reader: line numbers and unwind info only */
3532 ML_(read_debuginfo_dwarf3) ( di,
3533 debug_info_escn,
3534 debug_types_escn,
3535 debug_abbv_escn,
3536 debug_line_escn,
3537 debug_str_escn,
3538 debug_str_alt_escn,
3539 debug_line_str_escn);
3540 /* The new reader: read the DIEs in .debug_info to acquire
3541 information on variable types and locations or inline info.
3542 But only if the tool asks for it, or the user requests it on
3543 the command line. */
3544 if (VG_(clo_read_var_info) /* the user or tool asked for it */
3545 || VG_(clo_read_inline_info)) {
3546 ML_(new_dwarf3_reader)(
3547 di, debug_info_escn, debug_types_escn,
3548 debug_abbv_escn, debug_line_escn,
3549 debug_str_escn, debug_ranges_escn,
3550 debug_rnglists_escn, debug_loclists_escn,
3551 debug_loc_escn, debug_info_alt_escn,
3552 debug_abbv_alt_escn, debug_line_alt_escn,
3553 debug_str_alt_escn, debug_line_str_escn,
3554 debug_addr_escn, debug_str_offsets_escn
3559 /* TOPLEVEL */
3560 // JRS 31 July 2014: dwarf-1 reading is currently broken and
3561 // therefore deactivated.
3562 //if (dwarf1d_img && dwarf1l_img) {
3563 // ML_(read_debuginfo_dwarf1) ( di, dwarf1d_img, dwarf1d_sz,
3564 // dwarf1l_img, dwarf1l_sz );
3567 # if defined(VGA_arm)
3568 /* TOPLEVEL */
3569 /* ARM32 only: read .exidx/.extab if present. Note we are
3570 reading these directly out of the mapped in (running) image.
3571 Also, read these only if no CFI based unwind info was
3572 acquired for this file.
3574 An .exidx section is always required, but the .extab section
3575 can be optionally omitted, provided that .exidx does not
3576 refer to it. If the .exidx is erroneous and does refer to
3577 .extab even though .extab is missing, the range checks done
3578 by GET_EX_U32 in ExtabEntryExtract in readexidx.c should
3579 prevent any invalid memory accesses, and cause the .extab to
3580 be rejected as invalid.
3582 FIXME:
3583 * check with m_aspacemgr that the entire [exidx_avma, +exidx_size)
3584 and [extab_avma, +extab_size) areas are readable, since we're
3585 reading this stuff out of the running image (not from a file/socket)
3586 and we don't want to segfault.
3587 * DebugInfo::exidx_bias and use text_bias instead.
3588 I think it's always the same.
3589 * remove DebugInfo::{extab_bias, exidx_svma, extab_svma} since
3590 they are never used.
3592 if (di->exidx_present
3593 && di->cfsi_used == 0
3594 && di->text_present && di->text_size > 0) {
3595 Addr text_last_svma = di->text_svma + di->text_size - 1;
3596 ML_(read_exidx)( di, (UChar*)di->exidx_avma, di->exidx_size,
3597 (UChar*)di->extab_avma, di->extab_size,
3598 text_last_svma,
3599 di->exidx_bias );
3601 # endif /* defined(VGA_arm) */
3603 } /* "Find interesting sections, read the symbol table(s), read any debug
3604 information" (a local scope) */
3606 /* TOPLEVEL */
3607 res = True;
3609 /* If reading Dwarf3 variable type/location info, print a line
3610 showing the number of variables read for each object.
3611 (Currently disabled -- is a sanity-check mechanism for
3612 exp-sgcheck.) */
3613 if (0 && VG_(clo_read_var_info)) {
3614 UWord nVars = 0;
3615 if (di->varinfo) {
3616 for (j = 0; j < VG_(sizeXA)(di->varinfo); j++) {
3617 OSet* /* of DiAddrRange */ scope
3618 = *(OSet**)VG_(indexXA)(di->varinfo, j);
3619 vg_assert(scope);
3620 VG_(OSetGen_ResetIter)( scope );
3621 while (True) {
3622 DiAddrRange* range = VG_(OSetGen_Next)( scope );
3623 if (!range) break;
3624 vg_assert(range->vars);
3625 Word w = VG_(sizeXA)(range->vars);
3626 vg_assert(w >= 0);
3627 if (0) VG_(printf)("range %#lx %#lx %ld\n",
3628 range->aMin, range->aMax, w);
3629 nVars += (UWord)w;
3633 VG_(umsg)("VARINFO: %7lu vars %7lu text_size %s\n",
3634 nVars, di->text_size, di->fsm.filename);
3636 /* TOPLEVEL */
3638 out:
3640 /* Last, but not least, detach from the image(s). */
3641 if (mimg) ML_(img_done)(mimg);
3642 if (dimg) ML_(img_done)(dimg);
3643 if (aimg) ML_(img_done)(aimg);
3645 if (svma_ranges) VG_(deleteXA)(svma_ranges);
3647 return res;
3648 } /* out: */
3650 /* NOTREACHED */
3653 Bool ML_(check_elf_and_get_rw_loads) ( Int fd, const HChar* filename, Int * rw_load_count )
3655 Bool res, ok;
3656 UWord i;
3657 DiImage* mimg = NULL;
3658 DiOffT ehdr_mioff = 0;
3659 DiOffT phdr_mioff = 0;
3660 UWord phdr_mnent = 0U;
3661 UWord phdr_ment_szB = 0U;
3663 res = False;
3665 mimg = ML_(img_from_fd)(fd, filename);
3666 if (mimg == NULL) {
3667 VG_(message)(Vg_UserMsg, "warning: connection to image %s failed\n",
3668 filename );
3669 VG_(message)(Vg_UserMsg, " cannot read program headers \n" );
3670 return False;
3673 ok = is_elf_object_file_by_DiImage(mimg, False);
3674 if (!ok) {
3675 goto out;
3678 ElfXX_Ehdr ehdr_m;
3679 Elf64_Word flag_x;
3680 #if defined(VGA_amd64) || defined(VGA_ppc64be) || defined(VGA_ppc64le) || defined(VGA_arm) || defined(VGA_arm64)
3681 flag_x = PF_X;
3682 #else
3683 flag_x = 0;
3684 #endif
3686 #if defined(VGO_solaris)
3687 flag_x = 0;
3688 #endif
3690 vg_assert(ehdr_mioff == 0); // ensured by its initialisation
3691 ok = ML_(img_valid)(mimg, ehdr_mioff, sizeof(ehdr_m));
3692 vg_assert(ok); // ML_(is_elf_object_file) should ensure this
3693 ML_(img_get)(&ehdr_m, mimg, ehdr_mioff, sizeof(ehdr_m));
3695 phdr_mioff = ehdr_mioff + ehdr_m.e_phoff;
3696 phdr_mnent = ehdr_m.e_phnum;
3697 phdr_ment_szB = ehdr_m.e_phentsize;
3699 for (i = 0U; i < phdr_mnent; i++) {
3700 ElfXX_Phdr a_phdr;
3701 ML_(img_get)(&a_phdr, mimg,
3702 INDEX_BIS(phdr_mioff, i, phdr_ment_szB),
3703 sizeof(a_phdr));
3705 if (a_phdr.p_type == PT_LOAD) {
3706 if (a_phdr.p_memsz > 0) {
3707 if (((a_phdr.p_flags & (PF_R | PF_W)) == (PF_R | PF_W)) &&
3708 ((a_phdr.p_flags & flag_x) == 0)) {
3709 ++*rw_load_count;
3713 * Hold your horses
3714 * Just because The ELF file contains 2 RW PT_LOAD segments it
3715 * doesn't mean that Valgrind will also make 2 calls to
3716 * VG_(di_notify_mmap). If the stars are all aligned
3717 * (which usually means that the ELF file is the client
3718 * executable with the segment offset for the
3719 * second PT_LOAD falls exactly on 0x1000) then the NSegements
3720 * will get merged and VG_(di_notify_mmap) only gets called once. */
3721 if (*rw_load_count == 2 &&
3722 ehdr_m.e_type == ET_EXEC &&
3723 a_phdr.p_offset == VG_PGROUNDDN(a_phdr.p_offset) )
3725 *rw_load_count = 1;
3729 } /* for (i = 0; i < phdr_Mnent; i++) ... */
3731 res = True;
3733 out:
3735 /* Last, but not least, detach from the image(s). */
3736 if (mimg) ML_(img_free)(mimg);
3738 return res;
3739 } /* out: */
3741 /* NOTREACHED */
3746 #endif // defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
3748 /*--------------------------------------------------------------------*/
3749 /*--- end ---*/
3750 /*--------------------------------------------------------------------*/