Bug 439685 compiler warning in callgrind/main.c
[valgrind.git] / coregrind / m_debuginfo / readelf.c
blobce7b7998dea10f961e9e746636b8e3a0ec6f7d3d
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 || ELFXX_ST_BIND(sym->st_info) == STB_WEAK) {
434 *is_global_out = True;
437 # if defined(VGP_ppc64be_linux)
438 /* Allow STT_NOTYPE in the very special case where we're running on
439 ppc64be-linux and the symbol is one which the .opd-chasing hack
440 below will chase. */
441 if (!plausible
442 && *is_text_out
443 && ELFXX_ST_TYPE(sym->st_info) == STT_NOTYPE
444 && *sym_size_out > 0
445 && di->opd_present
446 && di->opd_size > 0
447 && (*sym_avmas_out).main >= di->opd_avma
448 && (*sym_avmas_out).main < di->opd_avma + di->opd_size)
449 plausible = True;
450 # endif
452 if (!plausible)
453 return False;
455 /* Ignore if nameless. */
456 if (sym_name_ioff == DiOffT_INVALID
457 || /* VG_(strlen)(sym_name) == 0 */
458 /* equivalent but cheaper ... */
459 ML_(img_get_UChar)(escn_strtab->img, sym_name_ioff) == '\0') {
460 if (TRACE_SYMTAB_ENABLED) {
461 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
462 "di.gesi.1", sym_name_ioff);
463 TRACE_SYMTAB(" ignore -- nameless: %s\n", sym_name);
464 if (sym_name) ML_(dinfo_free)(sym_name);
466 return False;
469 /* Ignore if zero-sized. Except on Android:
471 On Android 2.3.5, some of the symbols that Memcheck needs to
472 intercept (for noise reduction purposes) have zero size, due to
473 lack of .size directives in handwritten assembly sources. So we
474 can't reject them out of hand -- instead give them a bogusly
475 large size and let canonicaliseSymtab trim them so they don't
476 overlap any following symbols. At least the following symbols
477 are known to be affected:
479 in /system/lib/libc.so: strlen strcmp strcpy memcmp memcpy
480 in /system/bin/linker: __dl_strcmp __dl_strlen
482 if (*sym_size_out == 0) {
483 # if defined(VGPV_arm_linux_android) \
484 || defined(VGPV_x86_linux_android) \
485 || defined(VGPV_mips32_linux_android) \
486 || defined(VGPV_arm64_linux_android)
487 *sym_size_out = available_size ? available_size : 2048;
488 # else
489 if (TRACE_SYMTAB_ENABLED) {
490 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
491 "di.gesi.2", sym_name_ioff);
492 TRACE_SYMTAB(" ignore -- size=0: %s\n", sym_name);
493 if (sym_name) ML_(dinfo_free)(sym_name);
495 return False;
496 # endif
499 /* This seems to significantly reduce the number of junk
500 symbols, and particularly reduces the number of
501 overlapping address ranges. Don't ask me why ... */
502 if ((Int)sym->st_value == 0) {
503 if (TRACE_SYMTAB_ENABLED) {
504 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
505 "di.gesi.3", sym_name_ioff);
506 TRACE_SYMTAB( " ignore -- valu=0: %s\n", sym_name);
507 if (sym_name) ML_(dinfo_free)(sym_name);
509 return False;
512 /* If it's apparently in a GOT or PLT, it's really a reference to a
513 symbol defined elsewhere, so ignore it. */
514 if (di->got_present
515 && di->got_size > 0
516 && (*sym_avmas_out).main >= di->got_avma
517 && (*sym_avmas_out).main < di->got_avma + di->got_size) {
518 if (TRACE_SYMTAB_ENABLED) {
519 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
520 "di.gesi.4", sym_name_ioff);
521 TRACE_SYMTAB(" ignore -- in GOT: %s\n", sym_name);
522 if (sym_name) ML_(dinfo_free)(sym_name);
524 return False;
526 if (di->plt_present
527 && di->plt_size > 0
528 && (*sym_avmas_out).main >= di->plt_avma
529 && (*sym_avmas_out).main < di->plt_avma + di->plt_size) {
530 if (TRACE_SYMTAB_ENABLED) {
531 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
532 "di.gesi.5", sym_name_ioff);
533 TRACE_SYMTAB(" ignore -- in PLT: %s\n", sym_name);
534 if (sym_name) ML_(dinfo_free)(sym_name);
536 return False;
539 /* ppc64be-linux nasty hack: if the symbol is in an .opd section,
540 then really what we have is the address of a function
541 descriptor. So use the first word of that as the function's
542 text.
544 See thread starting at
545 http://gcc.gnu.org/ml/gcc-patches/2004-08/msg00557.html
547 # if defined(VGP_ppc64be_linux)
548 /* Host and guest may have different Endianness, used by BE only */
549 is_in_opd = False;
550 # endif
552 if (di->opd_present
553 && di->opd_size > 0
554 && (*sym_avmas_out).main >= di->opd_avma
555 && (*sym_avmas_out).main < di->opd_avma + di->opd_size) {
556 # if !defined(VGP_ppc64be_linux)
557 if (TRACE_SYMTAB_ENABLED) {
558 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
559 "di.gesi.6", sym_name_ioff);
560 TRACE_SYMTAB(" ignore -- in OPD: %s\n", sym_name);
561 if (sym_name) ML_(dinfo_free)(sym_name);
563 return False;
564 # else
565 Int offset_in_opd;
566 Bool details = 1||False;
568 if (details)
569 TRACE_SYMTAB("opdXXX: opd_bias %p, sym_svma_out %p\n",
570 (void*)(opd_bias), (void*)(*sym_avmas_out).main);
572 if (!VG_IS_8_ALIGNED((*sym_avmas_out).main)) {
573 if (TRACE_SYMTAB_ENABLED) {
574 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
575 "di.gesi.6a", sym_name_ioff);
576 TRACE_SYMTAB(" ignore -- not 8-aligned: %s\n", sym_name);
577 if (sym_name) ML_(dinfo_free)(sym_name);
579 return False;
582 /* (*sym_avmas_out).main is a avma pointing into the .opd section. We
583 know the vma of the opd section start, so we can figure out
584 how far into the opd section this is. */
586 offset_in_opd = (Addr)(*sym_avmas_out).main - (Addr)(di->opd_avma);
587 if (offset_in_opd < 0 || offset_in_opd >= di->opd_size) {
588 if (TRACE_SYMTAB_ENABLED) {
589 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
590 "di.gesi.6a", sym_name_ioff);
591 TRACE_SYMTAB(" ignore -- invalid OPD offset: %s\n", sym_name);
592 if (sym_name) ML_(dinfo_free)(sym_name);
594 return False;
597 /* Now we want to know what's at that offset in the .opd
598 section. We can't look in the running image since it won't
599 necessarily have been mapped. But we can consult the oimage.
600 opd_img is the start address of the .opd in the oimage.
601 Hence: */
603 ULong fn_descr[2]; /* is actually 3 words, but we need only 2 */
604 if (!ML_(img_valid)(escn_opd->img, escn_opd->ioff + offset_in_opd,
605 sizeof(fn_descr))) {
606 if (TRACE_SYMTAB_ENABLED) {
607 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
608 "di.gesi.6b", sym_name_ioff);
609 TRACE_SYMTAB(" ignore -- invalid OPD fn_descr offset: %s\n",
610 sym_name);
611 if (sym_name) ML_(dinfo_free)(sym_name);
614 return False;
617 /* This can't fail now, because we just checked the offset
618 above. */
619 ML_(img_get)(&fn_descr[0], escn_opd->img,
620 escn_opd->ioff + offset_in_opd, sizeof(fn_descr));
622 if (details)
623 TRACE_SYMTAB("opdXXY: offset %d, fn_descr %p\n",
624 offset_in_opd, fn_descr);
625 if (details)
626 TRACE_SYMTAB("opdXXZ: *fn_descr %p\n", (void*)(fn_descr[0]));
628 /* opd_bias is the what we have to add to SVMAs found in .opd to
629 get plausible .text AVMAs for the entry point, and .data
630 AVMAs (presumably) for the TOC locations. We use the caller
631 supplied value (which is di->text_bias) for both of these.
632 Not sure why that is correct - it seems to work, and sounds
633 OK for fn_descr[0], but surely we need to use the data bias
634 and not the text bias for fn_descr[1] ? Oh Well.
636 (*sym_avmas_out).main = fn_descr[0] + opd_bias;
637 SET_TOCPTR_AVMA(*sym_avmas_out, fn_descr[1] + opd_bias);
638 *from_opd_out = True;
639 is_in_opd = True;
641 /* Do a final sanity check: if the symbol falls outside the
642 DebugInfo's mapped range, ignore it. Since (*sym_avmas_out).main has
643 been updated, that can be achieved simply by falling through
644 to the test below. */
646 # endif /* ppc64-linux nasty hack */
649 /* Here's yet another ppc64-linux hack. Get rid of leading dot if
650 the symbol is outside .opd. */
651 # if defined(VGP_ppc64be_linux)
652 if (di->opd_size > 0
653 && !is_in_opd
654 && *sym_name_out_ioff != DiOffT_INVALID
655 && ML_(img_get_UChar)(escn_strtab->img, *sym_name_out_ioff) == '.') {
656 vg_assert(!(*from_opd_out));
657 (*sym_name_out_ioff)++;
659 # endif
661 /* If no part of the symbol falls within the mapped range,
662 ignore it. */
664 in_text
665 = di->text_present
666 && di->text_size > 0
667 && !((*sym_avmas_out).main + *sym_size_out <= di->text_avma
668 || (*sym_avmas_out).main >= di->text_avma + di->text_size);
670 in_data
671 = di->data_present
672 && di->data_size > 0
673 && !((*sym_avmas_out).main + *sym_size_out <= di->data_avma
674 || (*sym_avmas_out).main >= di->data_avma + di->data_size);
676 in_sdata
677 = di->sdata_present
678 && di->sdata_size > 0
679 && !((*sym_avmas_out).main + *sym_size_out <= di->sdata_avma
680 || (*sym_avmas_out).main >= di->sdata_avma + di->sdata_size);
682 in_rodata
683 = di->rodata_present
684 && di->rodata_size > 0
685 && !((*sym_avmas_out).main + *sym_size_out <= di->rodata_avma
686 || (*sym_avmas_out).main >= di->rodata_avma + di->rodata_size);
688 in_bss
689 = di->bss_present
690 && di->bss_size > 0
691 && !((*sym_avmas_out).main + *sym_size_out <= di->bss_avma
692 || (*sym_avmas_out).main >= di->bss_avma + di->bss_size);
694 in_sbss
695 = di->sbss_present
696 && di->sbss_size > 0
697 && !((*sym_avmas_out).main + *sym_size_out <= di->sbss_avma
698 || (*sym_avmas_out).main >= di->sbss_avma + di->sbss_size);
701 if (*is_text_out) {
702 /* This used to reject any symbol falling outside the text
703 segment ("if (!in_text) ..."). Now it is relaxed slightly,
704 to reject only symbols which fall outside the area mapped
705 r-x. This is in accordance with r7427. See
706 "Comment_Regarding_Text_Range_Checks" in storage.c for
707 background. */
708 Bool in_rx;
709 vg_assert(di->fsm.have_rx_map);
710 /* This could actually wrap around and cause
711 ML_(find_rx_mapping) to assert. But that seems so unlikely,
712 let's wait for it to happen before fixing it. */
713 in_rx = (ML_(find_rx_mapping)(
715 (*sym_avmas_out).main,
716 (*sym_avmas_out).main + *sym_size_out - 1) != NULL);
717 if (in_text)
718 vg_assert(in_rx);
719 if (!in_rx) {
720 TRACE_SYMTAB(
721 "ignore -- %#lx .. %#lx outside .text svma range %#lx .. %#lx\n",
722 (*sym_avmas_out).main, (*sym_avmas_out).main + *sym_size_out - 1,
723 di->text_avma,
724 di->text_avma + di->text_size - 1);
725 return False;
727 } else {
728 if (!(in_data || in_sdata || in_rodata || in_bss || in_sbss)) {
729 TRACE_SYMTAB(
730 "ignore -- %#lx .. %#lx outside .data / .sdata / .rodata "
731 "/ .bss / .sbss svma ranges\n",
732 (*sym_avmas_out).main, (*sym_avmas_out).main + *sym_size_out - 1);
733 return False;
737 # if defined(VGP_ppc64be_linux)
738 if (di->opd_present && di->opd_size > 0) {
739 vg_assert((*sym_avmas_out).main + *sym_size_out <= di->opd_avma
740 || (*sym_avmas_out).main >= di->opd_avma + di->opd_size);
742 #endif
744 # if defined(VGP_ppc64le_linux)
745 /* PPC64 LE ABI uses three bits in the st_other field to indicate the number
746 * of instructions between the function's global and local entry points. An
747 * offset of 0 indicates that there is one entry point. The value must be:
749 * 0 - one entry point, local and global are the same
750 * 1 - reserved
751 * 2 - local entry point is one instruction after the global entry point
752 * 3 - local entry point is two instructions after the global entry point
753 * 4 - local entry point is four instructions after the global entry point
754 * 5 - local entry point is eight instructions after the global entry point
755 * 6 - local entry point is sixteen instructions after the global entry point
756 * 7 - reserved
758 * Extract the three bit field from the other field is done by:
759 * (other_field & STO_PPC64_LOCAL_MASK) >> STO_PPC_LOCAL_BIT
761 * where the #define values are given in include/elf/powerpc.h file for
762 * the PPC binutils.
764 * conversion of the three bit field to bytes is given by
766 * ((1 << bit_field) >> 2) << 2
769 #define STO_PPC64_LOCAL_BIT 5
770 #define STO_PPC64_LOCAL_MASK (7 << STO_PPC64_LOCAL_BIT)
772 unsigned int bit_field, dist_to_local_entry;
773 /* extract the other filed */
774 bit_field = (sym->st_other & STO_PPC64_LOCAL_MASK) >> STO_PPC64_LOCAL_BIT;
776 if ((bit_field > 0) && (bit_field < 7)) {
777 /* store the local entry point address */
778 dist_to_local_entry = ((1 << bit_field) >> 2) << 2;
779 SET_LOCAL_EP_AVMA(*sym_avmas_out,
780 (*sym_avmas_out).main + dist_to_local_entry);
782 if (TRACE_SYMTAB_ENABLED) {
783 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
784 "di.gesi.5", sym_name_ioff);
785 VG_(printf)("Local entry point: %s at %#010x\n",
786 sym_name,
787 (unsigned int)GET_LOCAL_EP_AVMA(*sym_avmas_out));
791 # endif
793 /* Acquire! */
794 return True;
798 /* Read an ELF symbol table (normal or dynamic). This one is for the
799 "normal" case ({x86,amd64,ppc32,arm,mips32,mips64, ppc64le}-linux). */
800 static
801 __attribute__((unused)) /* not referred to on all targets */
802 void read_elf_symtab__normal(
803 struct _DebugInfo* di, const HChar* tab_name,
804 DiSlice* escn_symtab,
805 DiSlice* escn_strtab,
806 DiSlice* escn_opd, /* ppc64be-linux only */
807 Bool symtab_in_debug
810 if (escn_strtab->img == NULL || escn_symtab->img == NULL) {
811 HChar buf[VG_(strlen)(tab_name) + 40];
812 VG_(sprintf)(buf, " object doesn't have a %s", tab_name);
813 ML_(symerr)(di, False, buf);
814 return;
817 TRACE_SYMTAB("\n--- Reading (ELF, standard) %s (%llu entries) ---\n",
818 tab_name, escn_symtab->szB/sizeof(ElfXX_Sym) );
820 /* Perhaps should start at i = 1; ELF docs suggest that entry
821 0 always denotes 'unknown symbol'. */
822 Word i;
823 for (i = 1; i < (Word)(escn_symtab->szB/sizeof(ElfXX_Sym)); i++) {
824 ElfXX_Sym sym;
825 ML_(img_get)(&sym, escn_symtab->img,
826 escn_symtab->ioff + i * sizeof(ElfXX_Sym), sizeof(sym));
827 DiOffT sym_name = escn_strtab->ioff + sym.st_name;
828 Addr sym_svma = sym.st_value;
830 if (di->trace_symtab)
831 show_raw_elf_symbol(escn_strtab->img, i,
832 &sym, sym_name, sym_svma, False);
834 SymAVMAs sym_avmas_really;
835 Int sym_size = 0;
836 Bool from_opd = False, is_text = False, is_ifunc = False;
837 Bool is_global = False;
838 DiOffT sym_name_really = DiOffT_INVALID;
839 sym_avmas_really.main = 0;
840 SET_TOCPTR_AVMA(sym_avmas_really, 0);
841 SET_LOCAL_EP_AVMA(sym_avmas_really, 0);
842 if (get_elf_symbol_info(di, &sym, sym_name, escn_strtab,
843 sym_svma, symtab_in_debug,
844 escn_opd, di->text_bias,
845 &sym_name_really,
846 &sym_avmas_really,
847 &sym_size,
848 &from_opd, &is_text, &is_ifunc, &is_global)) {
850 DiSym disym;
851 VG_(memset)(&disym, 0, sizeof(disym));
852 HChar* cstr = ML_(img_strdup)(escn_strtab->img,
853 "di.res__n.1", sym_name_really);
854 disym.avmas = sym_avmas_really;
855 disym.pri_name = ML_(addStr) ( di, cstr, -1 );
856 disym.sec_names = NULL;
857 disym.size = sym_size;
858 disym.isText = is_text;
859 disym.isIFunc = is_ifunc;
860 disym.isGlobal = is_global;
861 if (cstr) { ML_(dinfo_free)(cstr); cstr = NULL; }
862 vg_assert(disym.pri_name);
863 vg_assert(GET_TOCPTR_AVMA(disym.avmas) == 0);
864 /* has no role except on ppc64be-linux */
865 ML_(addSym) ( di, &disym );
867 if (TRACE_SYMTAB_ENABLED) {
868 TRACE_SYMTAB(" rec(%c) [%4ld]: "
869 " val %#010lx, sz %4d %s\n",
870 is_text ? 't' : 'd',
872 disym.avmas.main,
873 (Int)disym.size,
874 disym.pri_name
876 if (GET_LOCAL_EP_AVMA(disym.avmas) != 0) {
877 TRACE_SYMTAB(" local entry point %#010lx\n",
878 GET_LOCAL_EP_AVMA(disym.avmas));
887 /* Read an ELF symbol table (normal or dynamic). This one is for
888 ppc64be-linux, which requires special treatment. */
890 typedef
891 struct {
892 Addr addr;
893 DiOffT name;
894 /* We have to store also the DiImage* so as to give context for
895 |name|. This is not part of the key (in terms of lookup) but
896 there's no easy other way to do this. Ugly. */
897 DiImage* img;
899 TempSymKey;
901 typedef
902 struct {
903 TempSymKey key;
904 Addr tocptr;
905 Int size;
906 Bool from_opd;
907 Bool is_text;
908 Bool is_ifunc;
909 Bool is_global;
911 TempSym;
913 static Word cmp_TempSymKey ( const TempSymKey* key1, const TempSym* elem2 )
915 /* Stay sane ... */
916 vg_assert(key1->img == elem2->key.img);
917 vg_assert(key1->img != NULL);
918 if (key1->addr < elem2->key.addr) return -1;
919 if (key1->addr > elem2->key.addr) return 1;
920 vg_assert(key1->name != DiOffT_INVALID);
921 vg_assert(elem2->key.name != DiOffT_INVALID);
922 return (Word)ML_(img_strcmp)(key1->img, key1->name, elem2->key.name);
925 static
926 __attribute__((unused)) /* not referred to on all targets */
927 void read_elf_symtab__ppc64be_linux(
928 struct _DebugInfo* di, const HChar* tab_name,
929 DiSlice* escn_symtab,
930 DiSlice* escn_strtab,
931 DiSlice* escn_opd, /* ppc64be-linux only */
932 Bool symtab_in_debug
935 Word i;
936 Int old_size;
937 Bool modify_size, modify_tocptr;
938 OSet *oset;
939 TempSymKey key;
940 TempSym *elem;
941 TempSym *prev;
943 if (escn_strtab->img == NULL || escn_symtab->img == NULL) {
944 HChar buf[VG_(strlen)(tab_name) + 40];
945 VG_(sprintf)(buf, " object doesn't have a %s", tab_name);
946 ML_(symerr)(di, False, buf);
947 return;
950 TRACE_SYMTAB("\n--- Reading (ELF, ppc64be-linux) %s (%llu entries) ---\n",
951 tab_name, escn_symtab->szB/sizeof(ElfXX_Sym) );
953 oset = VG_(OSetGen_Create)( offsetof(TempSym,key),
954 (OSetCmp_t)cmp_TempSymKey,
955 ML_(dinfo_zalloc), "di.respl.1",
956 ML_(dinfo_free) );
958 /* Perhaps should start at i = 1; ELF docs suggest that entry
959 0 always denotes 'unknown symbol'. */
960 for (i = 1; i < (Word)(escn_symtab->szB/sizeof(ElfXX_Sym)); i++) {
961 ElfXX_Sym sym;
962 ML_(img_get)(&sym, escn_symtab->img,
963 escn_symtab->ioff + i * sizeof(ElfXX_Sym), sizeof(sym));
964 DiOffT sym_name = escn_strtab->ioff + sym.st_name;
965 Addr sym_svma = sym.st_value;
967 if (di->trace_symtab)
968 show_raw_elf_symbol(escn_strtab->img, i,
969 &sym, sym_name, sym_svma, True);
971 SymAVMAs sym_avmas_really;
972 Int sym_size = 0;
973 Bool from_opd = False, is_text = False, is_ifunc = False;
974 Bool is_global = False;
975 DiOffT sym_name_really = DiOffT_INVALID;
976 DiSym disym;
977 VG_(memset)(&disym, 0, sizeof(disym));
978 sym_avmas_really.main = 0;
979 SET_TOCPTR_AVMA(sym_avmas_really, 0);
980 SET_LOCAL_EP_AVMA(sym_avmas_really, 0);
981 if (get_elf_symbol_info(di, &sym, sym_name, escn_strtab,
982 sym_svma, symtab_in_debug,
983 escn_opd, di->text_bias,
984 &sym_name_really,
985 &sym_avmas_really,
986 &sym_size,
987 &from_opd, &is_text, &is_ifunc, &is_global)) {
989 /* Check if we've seen this (name,addr) key before. */
990 key.addr = sym_avmas_really.main;
991 key.name = sym_name_really;
992 key.img = escn_strtab->img;
993 prev = VG_(OSetGen_Lookup)( oset, &key );
995 if (prev) {
997 /* Seen it before. Fold in whatever new info we can. */
998 modify_size = False;
999 modify_tocptr = False;
1000 old_size = 0;
1002 if (prev->from_opd && !from_opd
1003 && (prev->size == 24 || prev->size == 16)
1004 && sym_size != prev->size) {
1005 /* Existing one is an opd-redirect, with a bogus size,
1006 so the only useful new fact we have is the real size
1007 of the symbol. */
1008 modify_size = True;
1009 old_size = prev->size;
1010 prev->size = sym_size;
1012 else
1013 if (!prev->from_opd && from_opd
1014 && (sym_size == 24 || sym_size == 16)) {
1015 /* Existing one is non-opd, new one is opd. What we
1016 can acquire from the new one is the TOC ptr to be
1017 used. Since the existing sym is non-toc, it
1018 shouldn't currently have an known TOC ptr. */
1019 vg_assert(prev->tocptr == 0);
1020 modify_tocptr = True;
1021 prev->tocptr = GET_TOCPTR_AVMA(sym_avmas_really);
1023 else {
1024 /* ignore. can we do better here? */
1027 /* Only one or the other is possible (I think) */
1028 vg_assert(!(modify_size && modify_tocptr));
1030 if (modify_size && di->trace_symtab) {
1031 VG_(printf)(" modify (old sz %4d) "
1032 " val %#010lx, toc %#010lx, sz %4d %llu\n",
1033 old_size,
1034 prev->key.addr,
1035 prev->tocptr,
1036 prev->size,
1037 prev->key.name
1040 if (modify_tocptr && di->trace_symtab) {
1041 VG_(printf)(" modify (upd tocptr) "
1042 " val %#010lx, toc %#010lx, sz %4d %llu\n",
1043 prev->key.addr,
1044 prev->tocptr,
1045 prev->size,
1046 prev->key.name
1050 } else {
1052 /* A new (name,addr) key. Add and continue. */
1053 elem = VG_(OSetGen_AllocNode)(oset, sizeof(TempSym));
1054 elem->key = key;
1055 elem->tocptr = GET_TOCPTR_AVMA(sym_avmas_really);
1056 elem->size = sym_size;
1057 elem->from_opd = from_opd;
1058 elem->is_text = is_text;
1059 elem->is_ifunc = is_ifunc;
1060 elem->is_global = is_global;
1061 VG_(OSetGen_Insert)(oset, elem);
1062 if (di->trace_symtab) {
1063 HChar* str = ML_(img_strdup)(escn_strtab->img, "di.respl.2",
1064 elem->key.name);
1065 VG_(printf)(" to-oset [%4ld]: "
1066 " val %#010lx, toc %#010lx, sz %4d %s\n",
1068 elem->key.addr,
1069 elem->tocptr,
1070 (Int) elem->size,
1073 if (str) ML_(dinfo_free)(str);
1080 /* All the syms that matter are in the oset. Now pull them out,
1081 build a "standard" symbol table, and nuke the oset. */
1083 i = 0;
1084 VG_(OSetGen_ResetIter)( oset );
1086 while ( (elem = VG_(OSetGen_Next)(oset)) ) {
1087 DiSym disym;
1088 VG_(memset)(&disym, 0, sizeof(disym));
1089 HChar* cstr = ML_(img_strdup)(escn_strtab->img,
1090 "di.res__ppc64.1", elem->key.name);
1091 disym.avmas.main = elem->key.addr;
1092 SET_TOCPTR_AVMA(disym.avmas, elem->tocptr);
1093 SET_LOCAL_EP_AVMA(disym.avmas, 0); // ppc64be does not use local_ep.
1094 disym.pri_name = ML_(addStr) ( di, cstr, -1 );
1095 disym.sec_names = NULL;
1096 disym.size = elem->size;
1097 disym.isText = elem->is_text;
1098 disym.isIFunc = elem->is_ifunc;
1099 disym.isGlobal = elem->is_global;
1100 if (cstr) { ML_(dinfo_free)(cstr); cstr = NULL; }
1101 vg_assert(disym.pri_name != NULL);
1103 ML_(addSym) ( di, &disym );
1104 if (di->trace_symtab) {
1105 VG_(printf)(" rec(%c%c%c) [%4ld]: "
1106 " val %#010lx, toc %#010lx, sz %4d %s\n",
1107 disym.isText ? 't' : 'd',
1108 disym.isIFunc ? 'i' : '-',
1109 disym.isGlobal ? 'g' : 'l',
1111 disym.avmas.main,
1112 GET_TOCPTR_AVMA(disym.avmas),
1113 (Int) disym.size,
1114 disym.pri_name
1117 i++;
1120 VG_(OSetGen_Destroy)( oset );
1123 #if defined(VGO_freebsd)
1126 * read_and_set_osrel
1128 * "osrel" is in an Elf note. It has values such as 1201000 for FreeBSD 12.1
1129 * Some of the behaviour related to SIGSEGV and SIGBUS signals depends on the
1130 * kernel reading this value.
1132 * However in the case of Valgrind, the host is strictly statically linked and
1133 * does not contain the NT_FREEBSD_ABI_TAG note. And even if it did, we want to
1134 * override the value with that of the guest.
1136 * At some later date we might want to look at the value of "fctl0" (note with the
1137 * NT_FREEBSD_FEATURE_CTL type). This seems to be related to Address Space Layout
1138 * Randomization. No hurry at the moment.
1140 * See /usr/src/sys/kern/imgact_elf.c for details on how the kernel reads these
1141 * notes.
1143 static
1144 void read_and_set_osrel(DiImage* img)
1146 if (is_elf_object_file_by_DiImage(img, False)) {
1147 Word i;
1149 ElfXX_Ehdr ehdr;
1150 ML_(img_get)(&ehdr, img, 0, sizeof(ehdr));
1152 /* only set osrel for executable files, not for subsequent shared libraries */
1153 if (ehdr.e_type != ET_EXEC) {
1154 return;
1157 /* Skip the phdrs when we have to search the shdrs. In separate
1158 .debug files the phdrs might not be valid (they are a copy of
1159 the main ELF file) and might trigger assertions when getting
1160 image notes based on them. */
1161 for (i = 0; i < ehdr.e_phnum; i++) {
1162 ElfXX_Phdr phdr;
1163 ML_(img_get)(&phdr, img,
1164 ehdr.e_phoff + i * ehdr.e_phentsize, sizeof(phdr));
1166 if (phdr.p_type == PT_NOTE) {
1167 ElfXX_Off note_ioff = phdr.p_offset;
1169 while (note_ioff < phdr.p_offset + phdr.p_filesz) {
1170 ElfXX_Nhdr note[2];
1171 ML_(img_get)(note, img, (DiOffT)note_ioff, sizeof(note));
1172 DiOffT name_ioff = note_ioff + sizeof(ElfXX_Nhdr);
1173 //DiOffT desc_ioff = name_ioff + ((note[0].n_namesz + 3) & ~3);
1174 if (ML_(img_strcmp_c)(img, name_ioff, "FreeBSD") == 0
1175 && note[0].n_type == VKI_NT_FREEBSD_ABI_TAG) {
1177 u_int32_t osrel = note[1].n_type;
1178 int name[4];
1179 name[0] = CTL_KERN;
1180 name[1] = KERN_PROC;
1181 name[2] = KERN_PROC_OSREL;
1182 name[3] = VG_(getpid)();
1183 SizeT newlen = sizeof(osrel);
1184 Int error = VG_(sysctl)(name, 4, NULL, NULL, &osrel, newlen);
1185 if (error == -1) {
1186 VG_(message)(Vg_DebugMsg, "Warning: failed to set osrel for current process with value %u\n", osrel);
1187 } else {
1188 if (VG_(clo_verbosity) > 1) {
1189 VG_(message)(Vg_DebugMsg, "Set osrel for current process with value %u\n", osrel);
1193 note_ioff = note_ioff + sizeof(ElfXX_Nhdr)
1194 + ((note[0].n_namesz + 3) & ~3)
1195 + ((note[0].n_descsz + 3) & ~3);
1202 #endif
1205 * Look for a build-id in an ELF image. The build-id specification
1206 * can be found here:
1208 * http://fedoraproject.org/wiki/RolandMcGrath/BuildID
1210 * Returned string must be freed by the caller.
1212 static
1213 HChar* find_buildid(DiImage* img, Bool rel_ok, Bool search_shdrs)
1215 HChar* buildid = NULL;
1217 # ifdef NT_GNU_BUILD_ID
1218 if (is_elf_object_file_by_DiImage(img, rel_ok)) {
1219 Word i;
1221 ElfXX_Ehdr ehdr;
1222 ML_(img_get)(&ehdr, img, 0, sizeof(ehdr));
1223 /* Skip the phdrs when we have to search the shdrs. In separate
1224 .debug files the phdrs might not be valid (they are a copy of
1225 the main ELF file) and might trigger assertions when getting
1226 image notes based on them. */
1227 for (i = 0; !search_shdrs && i < ehdr.e_phnum; i++) {
1228 ElfXX_Phdr phdr;
1229 ML_(img_get)(&phdr, img,
1230 ehdr.e_phoff + i * ehdr.e_phentsize, sizeof(phdr));
1232 if (phdr.p_type == PT_NOTE) {
1233 ElfXX_Off note_ioff = phdr.p_offset;
1235 while (note_ioff < phdr.p_offset + phdr.p_filesz) {
1236 ElfXX_Nhdr note;
1237 ML_(img_get)(&note, img, (DiOffT)note_ioff, sizeof(note));
1238 DiOffT name_ioff = note_ioff + sizeof(ElfXX_Nhdr);
1239 DiOffT desc_ioff = name_ioff + ((note.n_namesz + 3) & ~3);
1240 if (ML_(img_strcmp_c)(img, name_ioff, ELF_NOTE_GNU) == 0
1241 && note.n_type == NT_GNU_BUILD_ID) {
1242 buildid = ML_(dinfo_zalloc)("di.fbi.1",
1243 note.n_descsz * 2 + 1);
1244 Word j;
1245 for (j = 0; j < note.n_descsz; j++) {
1246 UChar desc_j = ML_(img_get_UChar)(img, desc_ioff + j);
1247 VG_(sprintf)(buildid + VG_(strlen)(buildid),
1248 "%02x", (UInt)desc_j);
1252 note_ioff = note_ioff + sizeof(ElfXX_Nhdr)
1253 + ((note.n_namesz + 3) & ~3)
1254 + ((note.n_descsz + 3) & ~3);
1259 /* Normally we would only search shdrs for ET_REL files, but when
1260 we search for a separate .debug file phdrs might not be there
1261 (they are never loaded) or have been corrupted, so try again
1262 against shdrs. */
1263 if (buildid || (!rel_ok && !search_shdrs))
1264 return buildid;
1266 for (i = 0; i < ehdr.e_shnum; i++) {
1267 ElfXX_Shdr shdr;
1268 ML_(img_get)(&shdr, img,
1269 ehdr.e_shoff + i * ehdr.e_shentsize, sizeof(shdr));
1271 if (shdr.sh_type == SHT_NOTE) {
1272 ElfXX_Off note_ioff = shdr.sh_offset;
1274 while (note_ioff < shdr.sh_offset + shdr.sh_size) {
1275 ElfXX_Nhdr note;
1276 ML_(img_get)(&note, img, (DiOffT)note_ioff, sizeof(note));
1277 DiOffT name_ioff = note_ioff + sizeof(ElfXX_Nhdr);
1278 DiOffT desc_ioff = name_ioff + ((note.n_namesz + 3) & ~3);
1280 if (ML_(img_strcmp_c)(img, name_ioff, ELF_NOTE_GNU) == 0
1281 && note.n_type == NT_GNU_BUILD_ID) {
1282 buildid = ML_(dinfo_zalloc)("di.fbi.2",
1283 note.n_descsz * 2 + 1);
1284 Word j;
1285 for (j = 0; j < note.n_descsz; j++) {
1286 UChar desc_j = ML_(img_get_UChar)(img, desc_ioff + j);
1287 VG_(sprintf)(buildid + VG_(strlen)(buildid),
1288 "%02x", (UInt)desc_j);
1292 note_ioff = note_ioff + sizeof(ElfXX_Nhdr)
1293 + ((note.n_namesz + 3) & ~3)
1294 + ((note.n_descsz + 3) & ~3);
1299 # endif /* def NT_GNU_BUILD_ID */
1301 return buildid;
1305 /* Try and open a separate debug file, ignoring any where the CRC does
1306 not match the value from the main object file. Returned DiImage
1307 must be discarded by the caller.
1309 If |serverAddr| is NULL, |name| is expected to be a fully qualified
1310 (absolute) path to the file in the local filesystem. If
1311 |serverAddr| is non-NULL, it is expected to be an IPv4 and port
1312 spec of the form "d.d.d.d:d" or "d.d.d.d", and |name| is expected
1313 to be a plain filename (no path components at all).
1315 static
1316 DiImage* open_debug_file( const HChar* name, const HChar* buildid, UInt crc,
1317 Bool rel_ok, const HChar* serverAddr )
1319 DiImage* dimg
1320 = serverAddr ? ML_(img_from_di_server)(name, serverAddr)
1321 : ML_(img_from_local_file)(name);
1322 if (dimg == NULL)
1323 return NULL;
1325 if (VG_(clo_verbosity) > 1) {
1326 if (serverAddr)
1327 VG_(message)(Vg_DebugMsg, " Considering %s on server %s ..\n",
1328 name, serverAddr);
1329 else
1330 VG_(message)(Vg_DebugMsg, " Considering %s ..\n", name);
1333 /* We will always check the crc if we have one (altfiles don't have one)
1334 for now because we might be opening the main file again by any other
1335 name, and that obviously also has the same buildid. More efficient
1336 would be an fstat bases check or a check that the file actually
1337 contains .debug* sections. */
1338 if (buildid && crc == 0) {
1339 HChar* debug_buildid = find_buildid(dimg, rel_ok, True);
1340 if (debug_buildid == NULL || VG_(strcmp)(buildid, debug_buildid) != 0) {
1341 ML_(img_done)(dimg);
1342 if (VG_(clo_verbosity) > 1)
1343 VG_(message)(Vg_DebugMsg,
1344 " .. build-id mismatch (found %s wanted %s)\n",
1345 debug_buildid, buildid);
1346 ML_(dinfo_free)(debug_buildid);
1347 return NULL;
1349 ML_(dinfo_free)(debug_buildid);
1350 if (VG_(clo_verbosity) > 1)
1351 VG_(message)(Vg_DebugMsg, " .. build-id is valid\n");
1352 } else {
1353 UInt calccrc = ML_(img_calc_gnu_debuglink_crc32)(dimg);
1354 if (calccrc != crc) {
1355 ML_(img_done)(dimg);
1356 if (VG_(clo_verbosity) > 1)
1357 VG_(message)(Vg_DebugMsg,
1358 " .. CRC mismatch (computed %08x wanted %08x)\n", calccrc, crc);
1359 return NULL;
1362 if (VG_(clo_verbosity) > 1)
1363 VG_(message)(Vg_DebugMsg, " .. CRC is valid\n");
1366 return dimg;
1369 #if defined(VGO_linux)
1370 /* Return the path of the debuginfod-find executable. */
1371 static
1372 const HChar* debuginfod_find_path( void )
1374 static const HChar* path = (const HChar*) -1;
1376 if (path == (const HChar*) -1) {
1377 if (VG_(getenv)("DEBUGINFOD_URLS") == NULL
1378 || VG_(strcmp)("", VG_(getenv("DEBUGINFOD_URLS"))) == 0)
1379 path = NULL;
1380 else
1381 path = VG_(find_executable)("debuginfod-find");
1384 return path;
1387 /* Try to find a separate debug file with |buildid| via debuginfod. If found,
1388 return its DiImage. Searches for a local debuginfod-find executable and
1389 runs it in a child process in order to download the debug file. */
1390 static
1391 DiImage* find_debug_file_debuginfod( const HChar* objpath,
1392 HChar** debugpath,
1393 const HChar* buildid,
1394 const UInt crc, Bool rel_ok )
1396 # define BUF_SIZE 4096
1397 Int out_fds[2], err_fds[2]; /* pipe fds */
1398 DiImage* dimg = NULL; /* the img we found */
1399 HChar buf[BUF_SIZE]; /* executable output buffer */
1400 const HChar* path; /* executable path */
1401 SizeT len; /* number of bytes read int buf */
1402 Int ret; /* result of read call */
1404 if (buildid == NULL)
1405 return NULL;
1407 if ((path = debuginfod_find_path()) == NULL)
1408 return NULL;
1410 if (VG_(pipe)(out_fds) != 0
1411 || VG_(pipe)(err_fds) != 0)
1412 return NULL;
1414 if (VG_(clo_verbosity) > 1)
1415 VG_(umsg)("Downloading debug info for %s...\n", objpath);
1417 /* Run debuginfod-find to query servers for the debuginfo. */
1418 Int pid = VG_(fork)();
1419 if (pid == 0) {
1420 const HChar *argv[4] = { path, "debuginfo", buildid, (HChar*)0 };
1422 /* Redirect stdout and stderr */
1423 SysRes res = VG_(dup2)(out_fds[1], 1);
1424 if (sr_Res(res) < 0)
1425 VG_(exit)(1);
1427 res = VG_(dup2)(err_fds[1], 2);
1428 if (sr_Res(res) < 0)
1429 VG_(exit)(1);
1431 /* Disable extra stderr output since it does not play well with umesg */
1432 VG_(env_unsetenv)(VG_(client_envp), "DEBUGINFOD_VERBOSE", NULL);
1433 VG_(env_unsetenv)(VG_(client_envp), "DEBUGINFOD_PROGRESS", NULL);
1435 VG_(close)(out_fds[0]);
1436 VG_(close)(err_fds[0]);
1437 VG_(execv)(argv[0], argv);
1439 /* If we are still alive here, execv failed. */
1440 VG_(exit)(1);
1443 VG_(close)(out_fds[1]);
1444 VG_(close)(err_fds[1]);
1446 if (pid < 0) {
1447 if (VG_(clo_verbosity) > 1)
1448 VG_(umsg)("Server Error\n");
1449 goto out;
1451 VG_(waitpid)(pid, NULL, 0);
1453 /* Set dimg if download was successful. */
1454 len = 0;
1455 ret = -1;
1456 while (len >= 0 && len < BUF_SIZE) {
1457 ret = VG_(read)(out_fds[0], buf + len, BUF_SIZE - len);
1458 if (ret <= 0)
1459 break;
1460 len += ret;
1462 if (ret >= 0 && len > 0
1463 && buf[0] == '/' && buf[len-1] == '\n') {
1465 /* Remove newline from filename before trying to open debug file */
1466 buf[len-1] = '\0';
1467 dimg = open_debug_file(buf, buildid, crc, rel_ok, NULL);
1468 if (dimg != NULL) {
1469 /* Success */
1470 if (*debugpath)
1471 ML_(dinfo_free)(*debugpath);
1473 *debugpath = ML_(dinfo_strdup)("di.fdfd.1", buf);
1474 if (VG_(clo_verbosity) > 1)
1475 VG_(umsg)("Successfully downloaded debug file for %s\n",
1476 objpath);
1477 goto out;
1481 /* Download failed so try to print error message. */
1482 HChar* nl;
1483 if (VG_(read)(err_fds[0], buf, BUF_SIZE) > 0
1484 && (nl = VG_(strchr)(buf, '\n'))) {
1485 *nl = '\0';
1486 if (VG_(clo_verbosity) > 1)
1487 VG_(umsg)("%s\n", buf);
1488 } else
1489 if (VG_(clo_verbosity) > 1)
1490 VG_(umsg)("Server Error\n");
1492 out:
1493 VG_(close)(out_fds[0]);
1494 VG_(close)(err_fds[0]);
1495 return dimg;
1497 #endif
1499 /* Try to find a separate debug file for a given object file. If
1500 found, return its DiImage, which should be freed by the caller. If
1501 |buildid| is non-NULL, then a debug object matching it is
1502 acceptable. If |buildid| is NULL or doesn't specify a findable
1503 debug object, then we look in various places to find a file with
1504 the specified CRC. And if that doesn't work out then we give
1505 up. */
1506 static
1507 DiImage* find_debug_file( struct _DebugInfo* di,
1508 const HChar* objpath, const HChar* buildid,
1509 const HChar* debugname, UInt crc, Bool rel_ok )
1511 const HChar* extrapath = VG_(clo_extra_debuginfo_path);
1512 const HChar* serverpath = VG_(clo_debuginfo_server);
1514 DiImage* dimg = NULL; /* the img that we found */
1515 HChar* debugpath = NULL; /* where we found it */
1517 if (buildid != NULL) {
1518 debugpath = ML_(dinfo_zalloc)("di.fdf.1",
1519 VG_(strlen)(buildid) + 33);
1521 VG_(sprintf)(debugpath, "/usr/lib/debug/.build-id/%c%c/%s.debug",
1522 buildid[0], buildid[1], buildid + 2);
1524 dimg = open_debug_file(debugpath, buildid, 0, rel_ok, NULL);
1525 if (!dimg) {
1526 ML_(dinfo_free)(debugpath);
1527 debugpath = NULL;
1531 if (dimg == NULL && debugname != NULL) {
1532 HChar *objdir = ML_(dinfo_strdup)("di.fdf.2", objpath);
1533 HChar *usrmerge_objdir;
1534 HChar *objdirptr;
1536 if ((objdirptr = VG_(strrchr)(objdir, '/')) != NULL)
1537 *objdirptr = '\0';
1539 if ((objdirptr = VG_(strstr)(objdir, "usr")) != NULL)
1540 usrmerge_objdir = objdirptr + VG_(strlen)("usr");
1541 else
1542 usrmerge_objdir = NULL;
1544 debugpath = ML_(dinfo_zalloc)(
1545 "di.fdf.3",
1546 VG_(strlen)(objdir) + VG_(strlen)(debugname) + 64
1547 + (extrapath ? VG_(strlen)(extrapath) : 0)
1548 + (serverpath ? VG_(strlen)(serverpath) : 0));
1550 # define TRY_OBJDIR(format, ...) \
1551 do { \
1552 VG_(sprintf)(debugpath, format, __VA_ARGS__); \
1553 dimg = open_debug_file(debugpath, buildid, crc, rel_ok, NULL); \
1554 if (dimg != NULL) goto dimg_ok; \
1555 } while (0);
1557 # define TRY_OBJDIR_USRMERGE_OBJDIR(format) \
1558 do { \
1559 TRY_OBJDIR(format, objdir, debugname); \
1560 if (usrmerge_objdir != NULL) { \
1561 TRY_OBJDIR(format, usrmerge_objdir, debugname); \
1563 } while (0)
1565 if (debugname[0] == '/') {
1566 TRY_OBJDIR("%s", debugname);
1569 TRY_OBJDIR_USRMERGE_OBJDIR("%s/%s");
1570 TRY_OBJDIR_USRMERGE_OBJDIR("%s/.debug/%s");
1571 TRY_OBJDIR_USRMERGE_OBJDIR("/usr/lib/debug%s/%s");
1573 if (extrapath) {
1574 TRY_OBJDIR("%s%s/%s", extrapath, objdir, debugname);
1575 if (usrmerge_objdir != NULL)
1576 TRY_OBJDIR("%s%s/%s", extrapath, usrmerge_objdir, debugname);
1578 # undef TRY_OBJDIR
1579 # undef TRY_OBJDIRS
1581 if (serverpath) {
1582 /* When looking on the debuginfo server, always just pass the
1583 basename. */
1584 const HChar* basename = debugname;
1585 if (VG_(strstr)(basename, "/") != NULL) {
1586 basename = VG_(strrchr)(basename, '/') + 1;
1588 VG_(sprintf)(debugpath, "%s on %s", basename, serverpath);
1589 dimg = open_debug_file(basename, buildid, crc, rel_ok, serverpath);
1590 if (dimg) goto dimg_ok;
1593 dimg_ok:
1595 ML_(dinfo_free)(objdir);
1598 # if defined(VGO_linux)
1599 if (VG_(clo_enable_debuginfod) && dimg == NULL)
1600 dimg = find_debug_file_debuginfod(objpath, &debugpath, buildid, crc, rel_ok);
1601 # endif
1603 if (dimg != NULL) {
1604 vg_assert(debugpath);
1605 TRACE_SYMTAB("\n");
1606 TRACE_SYMTAB("------ Found a debuginfo file: %s\n", debugpath);
1608 /* Only set once, we might be called again for opening the altfile. */
1609 if (di->fsm.dbgname == NULL)
1610 di->fsm.dbgname = ML_(dinfo_strdup)("di.fdf.4", debugpath);
1613 if (debugpath)
1614 ML_(dinfo_free)(debugpath);
1616 return dimg;
1620 /* Try to find a separate debug file for a given object file, in a
1621 hacky and dangerous way: check only the --extra-debuginfo-path and
1622 the --debuginfo-server. And don't do a consistency check. */
1623 static
1624 DiImage* find_debug_file_ad_hoc( const DebugInfo* di,
1625 const HChar* objpath )
1627 const HChar* extrapath = VG_(clo_extra_debuginfo_path);
1628 const HChar* serverpath = VG_(clo_debuginfo_server);
1630 DiImage* dimg = NULL; /* the img that we found */
1631 HChar* debugpath = NULL; /* where we found it */
1633 HChar *objdir = ML_(dinfo_strdup)("di.fdfah.1", objpath);
1634 HChar *objdirptr;
1636 if ((objdirptr = VG_(strrchr)(objdir, '/')) != NULL)
1637 *objdirptr = '\0';
1639 debugpath = ML_(dinfo_zalloc)(
1640 "di.fdfah.3",
1641 VG_(strlen)(objdir) + 64
1642 + (extrapath ? VG_(strlen)(extrapath) : 0)
1643 + (serverpath ? VG_(strlen)(serverpath) : 0));
1645 if (extrapath) {
1646 VG_(sprintf)(debugpath, "%s/%s", extrapath, objpath);
1647 dimg = ML_(img_from_local_file)(debugpath);
1648 if (dimg != NULL) {
1649 if (VG_(clo_verbosity) > 1) {
1650 VG_(message)(Vg_DebugMsg, " Using (POSSIBLY MISMATCHED) %s\n",
1651 debugpath);
1653 goto dimg_ok;
1656 if (serverpath) {
1657 /* When looking on the debuginfo server, always just pass the
1658 basename. */
1659 const HChar* basename = objpath;
1660 if (VG_(strstr)(basename, "/") != NULL) {
1661 basename = VG_(strrchr)(basename, '/') + 1;
1663 VG_(sprintf)(debugpath, "%s on %s", basename, serverpath);
1664 dimg = ML_(img_from_di_server)(basename, serverpath);
1665 if (dimg != NULL) {
1666 if (VG_(clo_verbosity) > 1) {
1667 VG_(message)(Vg_DebugMsg, " Using (POSSIBLY MISMATCHED) %s\n",
1668 debugpath);
1670 goto dimg_ok;
1674 dimg_ok:
1676 ML_(dinfo_free)(objdir);
1678 if (dimg != NULL) {
1679 vg_assert(debugpath);
1680 TRACE_SYMTAB("\n");
1681 TRACE_SYMTAB("------ Found an ad_hoc debuginfo file: %s\n", debugpath);
1684 if (debugpath)
1685 ML_(dinfo_free)(debugpath);
1687 return dimg;
1691 static DiOffT INDEX_BIS ( DiOffT base, UWord idx, UWord scale ) {
1692 // This is a bit stupid. Really, idx and scale ought to be
1693 // 64-bit quantities, always.
1694 return base + (DiOffT)idx * (DiOffT)scale;
1698 /* Find the file offset corresponding to SVMA by using the program
1699 headers. This is taken from binutils-2.17/binutils/readelf.c
1700 offset_from_vma(). */
1701 static
1702 Word file_offset_from_svma ( /*OUT*/Bool* ok,
1703 Addr svma,
1704 DiImage* img,
1705 DiOffT phdr_ioff,
1706 Word phdr_nent,
1707 Word phdr_ent_szB )
1709 Word i;
1710 for (i = 0; i < phdr_nent; i++) {
1711 ElfXX_Phdr seg;
1712 ML_(img_get)(&seg, img,
1713 INDEX_BIS(phdr_ioff, i, phdr_ent_szB), sizeof(seg));
1714 if (seg.p_type != PT_LOAD)
1715 continue;
1716 if (svma >= (seg.p_vaddr & -seg.p_align)
1717 && svma + 1 <= seg.p_vaddr + seg.p_filesz) {
1718 *ok = True;
1719 return svma - seg.p_vaddr + seg.p_offset;
1722 *ok = False;
1723 return 0;
1726 /* Check if section is compressed and modify DiSlice if it is.
1727 Returns False in case of unsupported compression type.
1729 static Bool check_compression(ElfXX_Shdr* h, DiSlice* s) {
1730 if (h->sh_flags & SHF_COMPRESSED) {
1731 ElfXX_Chdr chdr;
1732 ML_(img_get)(&chdr, s->img, s->ioff, sizeof(ElfXX_Chdr));
1733 if (chdr.ch_type != ELFCOMPRESS_ZLIB)
1734 return False;
1735 s->ioff = ML_(img_mark_compressed_part)(s->img,
1736 s->ioff + sizeof(ElfXX_Chdr),
1737 s->szB - sizeof(ElfXX_Chdr),
1738 (SizeT)chdr.ch_size);
1739 s->szB = chdr.ch_size;
1740 } else if (h->sh_size > SIZE_OF_ZLIB_HEADER) {
1741 /* Read the zlib header. In this case, it should be "ZLIB"
1742 followed by the uncompressed section size, 8 bytes in BE order. */
1743 UChar tmp[SIZE_OF_ZLIB_HEADER];
1744 ML_(img_get)(tmp, s->img, s->ioff, SIZE_OF_ZLIB_HEADER);
1745 if (VG_(memcmp)(tmp, "ZLIB", 4) == 0) {
1746 SizeT size;
1747 # if (VG_WORDSIZE == 8)
1748 size = tmp[4]; size <<= 8;
1749 size += tmp[5]; size <<= 8;
1750 size += tmp[6]; size <<= 8;
1751 size += tmp[7]; size <<= 8;
1752 # else
1753 vg_assert((tmp[4] == 0) && (tmp[5] == 0) && (tmp[6] == 0)
1754 && (tmp[7] == 0));
1755 size = 0;
1756 # endif
1757 size += tmp[8]; size <<= 8;
1758 size += tmp[9]; size <<= 8;
1759 size += tmp[10]; size <<= 8;
1760 size += tmp[11];
1761 s->ioff = ML_(img_mark_compressed_part)(s->img,
1762 s->ioff + SIZE_OF_ZLIB_HEADER,
1763 s->szB - SIZE_OF_ZLIB_HEADER,
1764 size);
1765 s->szB = size;
1768 return True;
1771 /* Helper function to get the readlink path. Returns a copy of path if the
1772 file wasn't a symbolic link. Returns NULL on error. Unless NULL is
1773 returned the result needs to be released with dinfo_free.
1775 static HChar* readlink_path (const HChar *path)
1777 SizeT bufsiz = VG_(strlen)(path);
1778 HChar *buf = ML_(dinfo_strdup)("readlink_path.strdup", path);
1779 UInt tries = 6;
1781 while (tries > 0) {
1782 SysRes res;
1783 #if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
1784 res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD,
1785 (UWord)path, (UWord)buf, bufsiz);
1786 #elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
1787 res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz);
1788 #elif defined(VGO_solaris)
1789 res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD, (UWord)path,
1790 (UWord)buf, bufsiz);
1791 #else
1792 # error Unknown OS
1793 #endif
1794 if (sr_isError(res)) {
1795 if (sr_Err(res) == VKI_EINVAL)
1796 return buf; // It wasn't a symbolic link, return the strdup result.
1797 ML_(dinfo_free)(buf);
1798 return NULL;
1801 SSizeT r = sr_Res(res);
1802 if (r < 0) break;
1803 if (r == bufsiz) { // buffer too small; increase and retry
1804 bufsiz *= 2 + 16;
1805 buf = ML_(dinfo_realloc)("readlink_path.realloc", buf, bufsiz);
1806 tries--;
1807 continue;
1809 buf[r] = '\0';
1810 break;
1813 if (tries == 0) { // We tried, but weird long path?
1814 ML_(dinfo_free)(buf);
1815 return NULL;
1818 if (buf[0] == '/')
1819 return buf;
1821 /* Relative path, add link dir. */
1822 HChar *linkdirptr;
1823 SizeT linkdir_len = VG_(strlen)(path);
1824 if ((linkdirptr = VG_(strrchr)(path, '/')) != NULL)
1825 linkdir_len -= VG_(strlen)(linkdirptr + 1);
1827 SizeT buflen = VG_(strlen)(buf);
1828 SizeT needed = linkdir_len + buflen + 1;
1829 if (bufsiz < needed)
1830 buf = ML_(dinfo_realloc)("readlink_path.linkdir", buf, needed);
1832 VG_(memmove)(buf + linkdir_len, buf, buflen);
1833 VG_(memcpy)(buf, path, linkdir_len);
1834 buf[needed - 1] = '\0';
1836 return buf;
1839 /* The central function for reading ELF debug info. For the
1840 object/exe specified by the DebugInfo, find ELF sections, then read
1841 the symbols, line number info, file name info, CFA (stack-unwind
1842 info) and anything else we want, into the tables within the
1843 supplied DebugInfo.
1846 Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di )
1848 /* This function is long and complex. That, and the presence of
1849 nested scopes, means it's not always easy to see which parts are
1850 in loops/conditionals and which aren't. To make it easier to
1851 follow, points executed exactly once -- that is, those which are
1852 the top level of the function -- are marked TOPLEVEL.
1854 /* Consistent terminology for local variable names, without which
1855 it's almost unfollowably complex:
1857 In which file?
1858 in the main ELF file *_m*
1859 in the debuginfo file *_d*
1860 in the alt debuginfo file *_a*
1862 What kind of thing?
1863 _{m,d,a}img a DiImage*
1864 _{m,d,a}ioff an offset in the image (DiOffT)
1865 _{m,d,a}nent "number of entries"
1866 _{m,d,a}ent_szB "size in bytes of an entry"
1867 ehdr_{m,d,a} ELF header
1868 phdr Program header
1869 shdr Section header
1870 a_X a temporary X
1871 _escn an DiSlice (elf section info) variable
1872 szB size in bytes
1876 /* TOPLEVEL */
1877 Bool res, ok;
1878 Word i, j;
1879 Bool dynbss_present = False;
1880 Bool sdynbss_present = False;
1882 /* Image for the main ELF file we're working with. */
1883 DiImage* mimg = NULL;
1885 /* Ditto for any ELF debuginfo file that we might happen to load. */
1886 DiImage* dimg = NULL;
1888 /* Ditto for alternate ELF debuginfo file that we might happen to load. */
1889 DiImage* aimg = NULL;
1891 /* ELF header offset for the main file. Should be zero since the
1892 ELF header is at start of file. */
1893 DiOffT ehdr_mioff = 0;
1895 /* Program header table image addr, # entries, entry size */
1896 DiOffT phdr_mioff = 0;
1897 UWord phdr_mnent = 0;
1898 UWord phdr_ment_szB = 0;
1900 /* Section header image addr, # entries, entry size. Also the
1901 associated string table. */
1902 DiOffT shdr_mioff = 0;
1903 UWord shdr_mnent = 0;
1904 UWord shdr_ment_szB = 0;
1905 DiOffT shdr_strtab_mioff = 0;
1907 /* SVMAs covered by rx and rw segments and corresponding biases.
1908 Normally each object would provide just one rx and one rw area,
1909 but various ELF mangling tools create objects with multiple
1910 such entries, hence the generality. */
1911 typedef
1912 struct {
1913 Addr svma_base;
1914 Addr svma_limit;
1915 PtrdiffT bias;
1916 Bool exec;
1918 RangeAndBias;
1920 XArray* /* of RangeAndBias */ svma_ranges = NULL;
1922 # if defined(SOLARIS_PT_SUNDWTRACE_THRP)
1923 Addr dtrace_data_vaddr = 0;
1924 # endif
1926 vg_assert(di);
1927 vg_assert(di->fsm.have_rx_map == True);
1928 vg_assert(di->fsm.rw_map_count >= 1);
1929 vg_assert(di->have_dinfo == False);
1930 vg_assert(di->fsm.filename);
1931 vg_assert(!di->symtab);
1932 vg_assert(!di->loctab);
1933 vg_assert(!di->inltab);
1934 vg_assert(!di->cfsi_base);
1935 vg_assert(!di->cfsi_m_ix);
1936 vg_assert(!di->cfsi_rd);
1937 vg_assert(!di->cfsi_exprs);
1938 vg_assert(!di->strpool);
1939 vg_assert(!di->fndnpool);
1940 vg_assert(!di->soname);
1943 Bool has_nonempty_rx = False;
1944 Bool has_nonempty_rw = False;
1945 for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
1946 DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
1947 if (!map->rx && !map->rw)
1948 continue;
1949 if (map->rx && map->size > 0)
1950 has_nonempty_rx = True;
1951 if (map->rw && map->size > 0)
1952 has_nonempty_rw = True;
1953 /* If this doesn't hold true, it means that m_syswrap/m_aspacemgr
1954 managed to do a mapping where the start isn't page aligned.
1955 Which sounds pretty bogus to me. */
1956 vg_assert(VG_IS_PAGE_ALIGNED(map->avma));
1958 vg_assert(has_nonempty_rx);
1959 vg_assert(has_nonempty_rw);
1962 /* ----------------------------------------------------------
1963 At this point, there is very little information in the
1964 DebugInfo. We only know that something that looks like an ELF
1965 file has been mapped rx-ishly and rw-ishly as recorded in the
1966 di->fsm.maps array items. First we examine the file's ELF
1967 Program Header, and, by comparing that against the di->fsm.maps
1968 info, try to figure out the AVMAs for the sections we care
1969 about, that should have been mapped: text, data, sdata, bss,
1970 got, plt, and toc.
1971 ---------------------------------------------------------- */
1973 res = False;
1975 if (VG_(clo_verbosity) > 1 || VG_(clo_trace_redir))
1976 VG_(message)(Vg_DebugMsg, "Reading syms from %s\n",
1977 di->fsm.filename );
1979 /* Connect to the primary object image, so that we can read symbols
1980 and line number info out of it. It will be disconnected
1981 immediately thereafter; it is only connected transiently. */
1982 mimg = ML_(img_from_local_file)(di->fsm.filename);
1983 if (mimg == NULL) {
1984 VG_(message)(Vg_UserMsg, "warning: connection to image %s failed\n",
1985 di->fsm.filename );
1986 VG_(message)(Vg_UserMsg, " no symbols or debug info loaded\n" );
1987 return False;
1990 /* Ok, the object image is available. Now verify that it is a
1991 valid ELF .so or executable image. */
1992 ok = is_elf_object_file_by_DiImage(mimg, False);
1993 if (!ok) {
1994 ML_(symerr)(di, True, "Invalid ELF Header");
1995 goto out;
1998 /* Find where the program and section header tables are, and give
1999 up if either is missing or outside the image (bogus). */
2000 ElfXX_Ehdr ehdr_m;
2001 vg_assert(ehdr_mioff == 0); // ensured by its initialisation
2002 ok = ML_(img_valid)(mimg, ehdr_mioff, sizeof(ehdr_m));
2003 vg_assert(ok); // ML_(is_elf_object_file) should ensure this
2004 ML_(img_get)(&ehdr_m, mimg, ehdr_mioff, sizeof(ehdr_m));
2006 phdr_mioff = ehdr_mioff + ehdr_m.e_phoff;
2007 phdr_mnent = ehdr_m.e_phnum;
2008 phdr_ment_szB = ehdr_m.e_phentsize;
2010 shdr_mioff = ehdr_mioff + ehdr_m.e_shoff;
2011 shdr_mnent = ehdr_m.e_shnum;
2012 shdr_ment_szB = ehdr_m.e_shentsize;
2014 TRACE_SYMTAB("------ Basic facts about the object ------\n");
2015 TRACE_SYMTAB("object: n_oimage %llu\n",
2016 (ULong)ML_(img_size)(mimg));
2017 TRACE_SYMTAB("phdr: ioff %llu nent %lu ent_szB %lu\n",
2018 phdr_mioff, phdr_mnent, phdr_ment_szB);
2019 TRACE_SYMTAB("shdr: ioff %llu nent %lu ent_szB %lu\n",
2020 shdr_mioff, shdr_mnent, shdr_ment_szB);
2021 for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
2022 const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
2023 if (map->rx)
2024 TRACE_SYMTAB("rx_map: avma %#lx size %lu foff %lld\n",
2025 map->avma, map->size, (Long)map->foff);
2027 for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
2028 const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
2029 if (map->rw)
2030 TRACE_SYMTAB("rw_map: avma %#lx size %lu foff %lld\n",
2031 map->avma, map->size, (Long)map->foff);
2034 if (phdr_mnent == 0
2035 || !ML_(img_valid)(mimg, phdr_mioff, phdr_mnent * phdr_ment_szB)) {
2036 ML_(symerr)(di, True, "Missing or invalid ELF Program Header Table");
2037 goto out;
2040 if (shdr_mnent == 0
2041 || !ML_(img_valid)(mimg, shdr_mioff, shdr_mnent * shdr_ment_szB)) {
2042 ML_(symerr)(di, True, "Missing or invalid ELF Section Header Table");
2043 goto out;
2046 /* Also find the section header's string table, and validate. */
2047 /* checked previously by is_elf_object_file: */
2048 vg_assert(ehdr_m.e_shstrndx != SHN_UNDEF);
2050 // shdr_mioff is the offset of the section header table
2051 // and we need the ehdr_m.e_shstrndx'th entry
2052 { ElfXX_Shdr a_shdr;
2053 ML_(img_get)(&a_shdr, mimg,
2054 INDEX_BIS(shdr_mioff, ehdr_m.e_shstrndx, shdr_ment_szB),
2055 sizeof(a_shdr));
2056 shdr_strtab_mioff
2057 = ehdr_mioff /* isn't this always zero? */ + a_shdr.sh_offset;
2059 if (!ML_(img_valid)(mimg, shdr_strtab_mioff,
2060 1/*bogus, but we don't know the real size*/ )) {
2061 ML_(symerr)(di, True, "Invalid ELF Section Header String Table");
2062 goto out;
2066 TRACE_SYMTAB("shdr: string table at %llu\n", shdr_strtab_mioff);
2068 svma_ranges = VG_(newXA)(ML_(dinfo_zalloc), "di.relfdi.1",
2069 ML_(dinfo_free), sizeof(RangeAndBias));
2071 /* TOPLEVEL */
2072 /* Look through the program header table, and:
2073 - copy information from suitable PT_LOAD entries into svma_ranges
2074 - find (or fake up) the .soname for this object.
2076 TRACE_SYMTAB("\n");
2077 TRACE_SYMTAB("------ Examining the program headers ------\n");
2078 vg_assert(di->soname == NULL);
2080 /* TOPLEVEL */
2081 ElfXX_Addr prev_svma = 0;
2083 for (i = 0; i < phdr_mnent; i++) {
2084 ElfXX_Phdr a_phdr;
2085 ML_(img_get)(&a_phdr, mimg,
2086 INDEX_BIS(phdr_mioff, i, phdr_ment_szB),
2087 sizeof(a_phdr));
2089 /* Make sure the PT_LOADable entries are in order and
2090 non-overlapping. This in turn means the address ranges
2091 slurped into svma_ranges are in order and
2092 non-overlapping. */
2094 if (a_phdr.p_type == PT_LOAD) {
2095 TRACE_SYMTAB("PT_LOAD[%ld]: p_vaddr %#lx (prev %#lx)\n",
2096 i, (UWord)a_phdr.p_vaddr, (UWord)prev_svma);
2097 TRACE_SYMTAB("PT_LOAD[%ld]: p_offset %lu, p_filesz %lu,"
2098 " perms %c%c%c\n",
2099 i, (UWord)a_phdr.p_offset, (UWord)a_phdr.p_filesz,
2100 a_phdr.p_flags & PF_R ? 'r' : '-',
2101 a_phdr.p_flags & PF_W ? 'w' : '-',
2102 a_phdr.p_flags & PF_X ? 'x' : '-');
2103 if (a_phdr.p_vaddr < prev_svma) {
2104 ML_(symerr)(di, True,
2105 "ELF Program Headers are not in ascending order");
2106 goto out;
2108 prev_svma = a_phdr.p_vaddr;
2109 if (a_phdr.p_memsz > 0) {
2110 Bool loaded = False;
2111 for (j = 0; j < VG_(sizeXA)(di->fsm.maps); j++) {
2112 const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, j);
2113 if ( (map->rx || map->rw || map->ro)
2114 && map->size > 0 /* stay sane */
2115 && a_phdr.p_offset >= map->foff
2116 && a_phdr.p_offset < map->foff + map->size
2117 && a_phdr.p_offset + a_phdr.p_filesz
2118 <= map->foff + map->size) {
2119 RangeAndBias item;
2120 item.svma_base = a_phdr.p_vaddr;
2121 item.svma_limit = a_phdr.p_vaddr + a_phdr.p_memsz;
2122 item.bias = map->avma - map->foff
2123 + a_phdr.p_offset - a_phdr.p_vaddr;
2124 if (map->rw
2125 && (a_phdr.p_flags & (PF_R | PF_W))
2126 == (PF_R | PF_W)) {
2127 item.exec = False;
2128 VG_(addToXA)(svma_ranges, &item);
2129 TRACE_SYMTAB(
2130 "PT_LOAD[%ld]: acquired as rw, bias 0x%lx\n",
2131 i, (UWord)item.bias);
2132 loaded = True;
2134 if (map->rx
2135 && (a_phdr.p_flags & (PF_R | PF_X))
2136 == (PF_R | PF_X)) {
2137 item.exec = True;
2138 VG_(addToXA)(svma_ranges, &item);
2139 TRACE_SYMTAB(
2140 "PT_LOAD[%ld]: acquired as rx, bias 0x%lx\n",
2141 i, (UWord)item.bias);
2142 loaded = True;
2144 if (map->ro
2145 && (a_phdr.p_flags & (PF_R | PF_W | PF_X))
2146 == PF_R) {
2147 item.exec = False;
2148 VG_(addToXA)(svma_ranges, &item);
2149 TRACE_SYMTAB(
2150 "PT_LOAD[%ld]: acquired as ro, bias 0x%lx\n",
2151 i, (UWord)item.bias);
2152 loaded = True;
2156 if (!loaded) {
2157 # if defined(SOLARIS_PT_SUNDWTRACE_THRP)
2158 if ((a_phdr.p_memsz == VKI_PT_SUNWDTRACE_SIZE)
2159 && ((a_phdr.p_flags & (PF_R | PF_W | PF_X)) == PF_R)) {
2160 TRACE_SYMTAB("PT_LOAD[%ld]: ignore dtrace_data program "
2161 "header\n", i);
2162 dtrace_data_vaddr = a_phdr.p_vaddr;
2163 continue;
2165 # endif /* SOLARIS_PT_SUNDWTRACE_THRP */
2167 ML_(symerr)(di, False,
2168 "ELF section outside all mapped regions");
2169 /* This problem might be solved by further memory mappings.
2170 Avoid the vg_assert(!di->soname) at the beginning of this
2171 function if DYNAMIC section has been already processed. */
2172 if (di->soname) {
2173 ML_(dinfo_free)(di->soname);
2174 di->soname = NULL;
2176 goto out;
2181 /* Try to get the soname. If there isn't one, use "NONE".
2182 The seginfo needs to have some kind of soname in order to
2183 facilitate writing redirect functions, since all redirect
2184 specifications require a soname (pattern). */
2185 if (a_phdr.p_type == PT_DYNAMIC && di->soname == NULL) {
2186 Word stroff = -1;
2187 DiOffT strtab_mioff = DiOffT_INVALID;
2188 for (j = 0; True/*exit check is in the loop*/; j++) {
2189 ElfXX_Dyn t_dyn_m; /* dyn_img[j] */
2190 ML_(img_get)(&t_dyn_m, mimg,
2191 INDEX_BIS(ehdr_mioff + a_phdr.p_offset,
2192 j, sizeof(ElfXX_Dyn)),
2193 sizeof(t_dyn_m));
2194 if (t_dyn_m.d_tag == DT_NULL)
2195 break;
2197 switch (t_dyn_m.d_tag) {
2198 case DT_SONAME: {
2199 stroff = t_dyn_m.d_un.d_val;
2200 break;
2202 case DT_STRTAB: {
2203 Bool ok2 = False;
2204 Word offset = file_offset_from_svma(
2205 &ok2, t_dyn_m.d_un.d_ptr, mimg,
2206 phdr_mioff, phdr_mnent, phdr_ment_szB
2208 if (ok2 && strtab_mioff == DiOffT_INVALID) {
2209 // Check for obviously bogus offsets.
2210 if (!ML_(img_valid)(mimg, offset, 1)) {
2211 ML_(symerr)(di, True, "Invalid DT_STRTAB offset");
2212 goto out;
2214 strtab_mioff = ehdr_mioff + offset;
2215 vg_assert(ehdr_mioff == 0); // should always be
2217 break;
2219 default:
2220 break;
2223 if (stroff != -1 && strtab_mioff != DiOffT_INVALID) {
2224 di->soname = ML_(img_strdup)(mimg, "di.redi.1",
2225 strtab_mioff + stroff);
2226 TRACE_SYMTAB("Found soname = %s\n", di->soname);
2229 } /* for (i = 0; i < phdr_Mnent; i++) ... */
2230 /* TOPLEVEL */
2232 } /* examine the program headers (local scope) */
2234 /* TOPLEVEL */
2236 /* If, after looking at all the program headers, we still didn't
2237 find a soname, add a fake one. */
2238 if (di->soname == NULL) {
2239 TRACE_SYMTAB("No soname found; using (fake) \"NONE\"\n");
2240 di->soname = ML_(dinfo_strdup)("di.redi.2", "NONE");
2243 vg_assert(VG_(sizeXA)(svma_ranges) != 0);
2245 /* Now read the section table. */
2246 TRACE_SYMTAB("\n");
2247 TRACE_SYMTAB("------ Examining the section headers ------\n");
2248 for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
2249 const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
2250 if (map->rx)
2251 TRACE_SYMTAB("rx: at %#lx are mapped foffsets %lld .. %lld\n",
2252 map->avma, (Long)map->foff, (Long)(map->foff + map->size - 1) );
2254 TRACE_SYMTAB("rx: contains these svma regions:\n");
2255 for (i = 0; i < VG_(sizeXA)(svma_ranges); i++) {
2256 const RangeAndBias* reg = VG_(indexXA)(svma_ranges, i);
2257 if (reg->exec)
2258 TRACE_SYMTAB(" svmas %#lx .. %#lx with bias %#lx\n",
2259 reg->svma_base, reg->svma_limit - 1, (UWord)reg->bias );
2261 for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
2262 const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
2263 if (map->rw) {
2264 TRACE_SYMTAB("rw: at %#lx are mapped foffsets %lld .. %lld\n",
2265 map->avma, (Long)map->foff, (Long)(map->foff + map->size - 1) );
2268 TRACE_SYMTAB("rw: contains these svma regions:\n");
2269 for (i = 0; i < VG_(sizeXA)(svma_ranges); i++) {
2270 const RangeAndBias* reg = VG_(indexXA)(svma_ranges, i);
2271 if (!reg->exec)
2272 TRACE_SYMTAB(" svmas %#lx .. %#lx with bias %#lx\n",
2273 reg->svma_base, reg->svma_limit - 1, (UWord)reg->bias );
2276 /* TOPLEVEL */
2277 /* Iterate over section headers */
2278 for (i = 0; i < shdr_mnent; i++) {
2279 ElfXX_Shdr a_shdr;
2280 ML_(img_get)(&a_shdr, mimg,
2281 INDEX_BIS(shdr_mioff, i, shdr_ment_szB), sizeof(a_shdr));
2282 DiOffT name_mioff = shdr_strtab_mioff + a_shdr.sh_name;
2283 HChar* name = ML_(img_strdup)(mimg, "di.redi_name.2", name_mioff);
2284 Addr svma = a_shdr.sh_addr;
2285 OffT foff = a_shdr.sh_offset;
2286 UWord size = a_shdr.sh_size; /* Do not change this to be signed. */
2287 UInt alyn = a_shdr.sh_addralign;
2288 Bool nobits = a_shdr.sh_type == SHT_NOBITS;
2289 /* Look through our collection of info obtained from the PT_LOAD
2290 headers, and make 'inrx' and 'inrw1' point to the first entry
2291 in each that intersects 'avma'. If in each case none is found,
2292 leave the relevant pointer at NULL. */
2293 RangeAndBias* inrx = NULL;
2294 RangeAndBias* inrw1 = NULL;
2295 /* Depending on the link editro there may be two RW PT_LOAD headers
2296 * If so this will point to the seond one */
2297 RangeAndBias* inrw2 = NULL;
2298 /* used to switch between inrw1 and inrw2 */
2299 RangeAndBias* inrw;
2301 for (j = 0; j < VG_(sizeXA)(svma_ranges); j++) {
2302 RangeAndBias* rng = VG_(indexXA)(svma_ranges, j);
2303 if (svma >= rng->svma_base && svma < rng->svma_limit) {
2304 if (!inrx && rng->exec) {
2305 inrx = rng;
2306 } else if (!inrw1 && !rng->exec) {
2307 inrw1 = rng;
2308 } else if (!inrw2 && !rng->exec) {
2309 inrw2 = rng;
2314 TRACE_SYMTAB(" [sec %2ld] %s %s %s al%4u foff %6lld .. %6lld "
2315 " svma %p name \"%s\"\n",
2316 i, inrx ? "rx" : " ", inrw1 ? "rw" : " ", inrw2 ? "rw" : " ",
2317 alyn, (Long) foff, (size == 0) ? (Long)foff : (Long)(foff+size-1),
2318 (void *) svma, name);
2320 /* Check for sane-sized segments. SHT_NOBITS sections have zero
2321 size in the file and their offsets are just conceptual. */
2322 if (!nobits &&
2323 (foff >= ML_(img_size)(mimg) || foff + size > ML_(img_size)(mimg))) {
2324 ML_(symerr)(di, True, "ELF Section extends beyond image end");
2325 goto out;
2328 /* Check for a sane alignment value. */
2329 if (alyn > 0 && -1 == VG_(log2)(alyn)) {
2330 ML_(symerr)(di, True, "ELF Section contains invalid "
2331 ".sh_addralign value");
2332 goto out;
2335 /* Ignore zero sized sections. */
2336 if (size == 0) {
2337 TRACE_SYMTAB("zero sized section \"%s\", ignoring\n", name);
2338 ML_(dinfo_free)(name);
2339 continue;
2342 # define BAD(_secname) \
2343 do { ML_(symerr)(di, True, \
2344 "Can't make sense of " _secname \
2345 " section mapping"); \
2346 /* make sure we don't assert if we find */ \
2347 /* ourselves back in this routine later, */ \
2348 /* with the same di */ \
2349 di->soname = NULL; \
2350 goto out; \
2351 } while (0)
2353 /* Find avma-s for: .text .data .sdata .rodata .bss .sbss .plt .got .opd
2354 and .eh_frame */
2356 /* In inrw2 is non-NULL then it will be used for .data .got.plt .bss */
2358 /* Accept .text where mapped as rx (code), even if zero-sized */
2359 if (0 == VG_(strcmp)(name, ".text")) {
2360 if (inrx && !di->text_present) {
2361 di->text_present = True;
2362 di->text_svma = svma;
2363 di->text_avma = svma + inrx->bias;
2364 di->text_size = size;
2365 di->text_bias = inrx->bias;
2366 di->text_debug_svma = svma;
2367 di->text_debug_bias = inrx->bias;
2368 TRACE_SYMTAB("acquiring .text svma = %#lx .. %#lx\n",
2369 di->text_svma,
2370 di->text_svma + di->text_size - 1);
2371 TRACE_SYMTAB("acquiring .text avma = %#lx .. %#lx\n",
2372 di->text_avma,
2373 di->text_avma + di->text_size - 1);
2374 TRACE_SYMTAB("acquiring .text bias = %#lx\n", (UWord)di->text_bias);
2375 } else {
2376 BAD(".text");
2380 /* Accept .data where mapped as rw (data), even if zero-sized */
2381 if (0 == VG_(strcmp)(name, ".data")) {
2382 # if defined(SOLARIS_PT_SUNDWTRACE_THRP)
2383 if ((size == VKI_PT_SUNWDTRACE_SIZE) && (svma == dtrace_data_vaddr)) {
2384 TRACE_SYMTAB("ignoring .data section for dtrace_data "
2385 "%#lx .. %#lx\n", svma, svma + size - 1);
2386 } else
2387 # endif /* SOLARIS_PT_SUNDWTRACE_THRP */
2389 if (inrw2) {
2390 inrw = inrw2;
2391 } else {
2392 inrw = inrw1;
2395 if (inrw && !di->data_present) {
2396 di->data_present = True;
2397 di->data_svma = svma;
2398 di->data_avma = svma + inrw->bias;
2399 di->data_size = size;
2400 di->data_bias = inrw->bias;
2401 di->data_debug_svma = svma;
2402 di->data_debug_bias = inrw->bias;
2403 TRACE_SYMTAB("acquiring .data svma = %#lx .. %#lx\n",
2404 di->data_svma,
2405 di->data_svma + di->data_size - 1);
2406 TRACE_SYMTAB("acquiring .data avma = %#lx .. %#lx\n",
2407 di->data_avma,
2408 di->data_avma + di->data_size - 1);
2409 TRACE_SYMTAB("acquiring .data bias = %#lx\n", (UWord)di->data_bias);
2410 } else {
2411 BAD(".data");
2415 /* Accept .sdata where mapped as rw (data) */
2416 if (0 == VG_(strcmp)(name, ".sdata")) {
2417 if (inrw1 && !di->sdata_present) {
2418 di->sdata_present = True;
2419 di->sdata_svma = svma;
2420 di->sdata_avma = svma + inrw1->bias;
2421 di->sdata_size = size;
2422 di->sdata_bias = inrw1->bias;
2423 di->sdata_debug_svma = svma;
2424 di->sdata_debug_bias = inrw1->bias;
2425 TRACE_SYMTAB("acquiring .sdata svma = %#lx .. %#lx\n",
2426 di->sdata_svma,
2427 di->sdata_svma + di->sdata_size - 1);
2428 TRACE_SYMTAB("acquiring .sdata avma = %#lx .. %#lx\n",
2429 di->sdata_avma,
2430 di->sdata_avma + di->sdata_size - 1);
2431 TRACE_SYMTAB("acquiring .sdata bias = %#lx\n",
2432 (UWord)di->sdata_bias);
2433 } else {
2434 BAD(".sdata");
2438 /* Accept .rodata where mapped as rx or rw (data), even if zero-sized */
2439 if (0 == VG_(strcmp)(name, ".rodata")) {
2440 if (!di->rodata_present) {
2441 di->rodata_svma = svma;
2442 di->rodata_avma = svma;
2443 di->rodata_size = size;
2444 di->rodata_debug_svma = svma;
2445 if (inrx) {
2446 di->rodata_avma += inrx->bias;
2447 di->rodata_bias = inrx->bias;
2448 di->rodata_debug_bias = inrx->bias;
2449 } else if (inrw1) {
2450 di->rodata_avma += inrw1->bias;
2451 di->rodata_bias = inrw1->bias;
2452 di->rodata_debug_bias = inrw1->bias;
2453 } else {
2454 BAD(".rodata");
2456 di->rodata_present = True;
2457 TRACE_SYMTAB("acquiring .rodata svma = %#lx .. %#lx\n",
2458 di->rodata_svma,
2459 di->rodata_svma + di->rodata_size - 1);
2460 TRACE_SYMTAB("acquiring .rodata avma = %#lx .. %#lx\n",
2461 di->rodata_avma,
2462 di->rodata_avma + di->rodata_size - 1);
2463 TRACE_SYMTAB("acquiring .rodata bias = %#lx\n",
2464 (UWord)di->rodata_bias);
2465 } else {
2466 BAD(".rodata");
2470 if (0 == VG_(strcmp)(name, ".dynbss")) {
2471 if (inrw1 && !di->bss_present) {
2472 dynbss_present = True;
2473 di->bss_present = True;
2474 di->bss_svma = svma;
2475 di->bss_avma = svma + inrw1->bias;
2476 di->bss_size = size;
2477 di->bss_bias = inrw1->bias;
2478 di->bss_debug_svma = svma;
2479 di->bss_debug_bias = inrw1->bias;
2480 TRACE_SYMTAB("acquiring .dynbss svma = %#lx .. %#lx\n",
2481 di->bss_svma,
2482 di->bss_svma + di->bss_size - 1);
2483 TRACE_SYMTAB("acquiring .dynbss avma = %#lx .. %#lx\n",
2484 di->bss_avma,
2485 di->bss_avma + di->bss_size - 1);
2486 TRACE_SYMTAB("acquiring .dynbss bias = %#lx\n",
2487 (UWord)di->bss_bias);
2491 /* Accept .bss where mapped as rw (data), even if zero-sized */
2492 if (0 == VG_(strcmp)(name, ".bss")) {
2494 if (inrw2) {
2495 inrw = inrw2;
2496 } else {
2497 inrw = inrw1;
2500 if (inrw && dynbss_present) {
2501 vg_assert(di->bss_present);
2502 dynbss_present = False;
2503 vg_assert(di->bss_svma + di->bss_size == svma);
2504 di->bss_size += size;
2505 TRACE_SYMTAB("acquiring .bss svma = %#lx .. %#lx\n",
2506 svma, svma + size - 1);
2507 TRACE_SYMTAB("acquiring .bss avma = %#lx .. %#lx\n",
2508 svma + inrw->bias, svma + inrw->bias + size - 1);
2509 TRACE_SYMTAB("acquiring .bss bias = %#lx\n",
2510 (UWord)di->bss_bias);
2511 } else
2513 if (inrw && !di->bss_present) {
2514 di->bss_present = True;
2515 di->bss_svma = svma;
2516 di->bss_avma = svma + inrw->bias;
2517 di->bss_size = size;
2518 di->bss_bias = inrw->bias;
2519 di->bss_debug_svma = svma;
2520 di->bss_debug_bias = inrw->bias;
2521 TRACE_SYMTAB("acquiring .bss svma = %#lx .. %#lx\n",
2522 di->bss_svma,
2523 di->bss_svma + di->bss_size - 1);
2524 TRACE_SYMTAB("acquiring .bss avma = %#lx .. %#lx\n",
2525 di->bss_avma,
2526 di->bss_avma + di->bss_size - 1);
2527 TRACE_SYMTAB("acquiring .bss bias = %#lx\n",
2528 (UWord)di->bss_bias);
2529 } else
2531 /* Now one from the wtf?! department ... */
2532 if (inrx && (!inrw) && !di->bss_present) {
2533 /* File contains a .bss, but it got mapped as rx only.
2534 This is very strange. For now, just pretend we didn't
2535 see it :-) */
2536 di->bss_present = False;
2537 di->bss_svma = 0;
2538 di->bss_avma = 0;
2539 di->bss_size = 0;
2540 di->bss_bias = 0;
2541 di->bss_debug_svma = 0;
2542 di->bss_debug_bias = 0;
2543 if (!VG_(clo_xml)) {
2544 VG_(message)(Vg_UserMsg,
2545 "Warning: the following file's .bss is "
2546 "mapped r-x only - ignoring .bss syms\n");
2547 VG_(message)(Vg_UserMsg, " %s\n", di->fsm.filename
2548 ? di->fsm.filename
2549 : "(null?!)" );
2551 } else
2553 if ((!inrw) && (!inrx) && !di->bss_present) {
2554 /* File contains a .bss, but it didn't get mapped. Ignore. */
2555 di->bss_present = False;
2556 di->bss_svma = 0;
2557 di->bss_avma = 0;
2558 di->bss_size = 0;
2559 di->bss_bias = 0;
2560 } else {
2561 BAD(".bss");
2565 if (0 == VG_(strcmp)(name, ".sdynbss")) {
2566 if (inrw1 && !di->sbss_present) {
2567 sdynbss_present = True;
2568 di->sbss_present = True;
2569 di->sbss_svma = svma;
2570 di->sbss_avma = svma + inrw1->bias;
2571 di->sbss_size = size;
2572 di->sbss_bias = inrw1->bias;
2573 di->sbss_debug_svma = svma;
2574 di->sbss_debug_bias = inrw1->bias;
2575 TRACE_SYMTAB("acquiring .sdynbss svma = %#lx .. %#lx\n",
2576 di->sbss_svma,
2577 di->sbss_svma + di->sbss_size - 1);
2578 TRACE_SYMTAB("acquiring .sdynbss avma = %#lx .. %#lx\n",
2579 di->sbss_avma,
2580 di->sbss_avma + di->sbss_size - 1);
2581 TRACE_SYMTAB("acquiring .sdynbss bias = %#lx\n",
2582 (UWord)di->sbss_bias);
2586 /* Accept .sbss where mapped as rw (data) */
2587 if (0 == VG_(strcmp)(name, ".sbss")) {
2588 if (inrw1 && sdynbss_present) {
2589 vg_assert(di->sbss_present);
2590 sdynbss_present = False;
2591 vg_assert(di->sbss_svma + di->sbss_size == svma);
2592 di->sbss_size += size;
2593 TRACE_SYMTAB("acquiring .sbss svma = %#lx .. %#lx\n",
2594 svma, svma + size - 1);
2595 TRACE_SYMTAB("acquiring .sbss avma = %#lx .. %#lx\n",
2596 svma + inrw1->bias, svma + inrw1->bias + size - 1);
2597 TRACE_SYMTAB("acquiring .sbss bias = %#lx\n", (UWord)di->sbss_bias);
2598 } else
2600 if (inrw1 && !di->sbss_present) {
2601 di->sbss_present = True;
2602 di->sbss_svma = svma;
2603 di->sbss_avma = svma + inrw1->bias;
2604 di->sbss_size = size;
2605 di->sbss_bias = inrw1->bias;
2606 di->sbss_debug_svma = svma;
2607 di->sbss_debug_bias = inrw1->bias;
2608 TRACE_SYMTAB("acquiring .sbss svma = %#lx .. %#lx\n",
2609 di->sbss_svma,
2610 di->sbss_svma + di->sbss_size - 1);
2611 TRACE_SYMTAB("acquiring .sbss avma = %#lx .. %#lx\n",
2612 di->sbss_avma,
2613 di->sbss_avma + di->sbss_size - 1);
2614 TRACE_SYMTAB("acquiring .sbss bias = %#lx\n", (UWord)di->sbss_bias);
2615 } else {
2616 BAD(".sbss");
2620 /* Accept .got where mapped as rw (data) */
2621 if (0 == VG_(strcmp)(name, ".got")) {
2622 if (inrw1 && !di->got_present) {
2623 di->got_present = True;
2624 di->got_avma = svma + inrw1->bias;
2625 di->got_size = size;
2626 TRACE_SYMTAB("acquiring .got avma = %#lx\n", di->got_avma);
2627 } else {
2628 BAD(".got");
2632 /* Accept .got.plt where mapped as rw (data) */
2633 if (0 == VG_(strcmp)(name, ".got.plt")) {
2635 if (inrw2) {
2636 inrw = inrw2;
2637 } else {
2638 inrw = inrw1;
2641 if (inrw && !di->gotplt_present) {
2642 di->gotplt_present = True;
2643 di->gotplt_avma = svma + inrw->bias;
2644 di->gotplt_size = size;
2645 TRACE_SYMTAB("acquiring .got.plt avma = %#lx\n", di->gotplt_avma);
2646 } else if (size != 0) {
2647 BAD(".got.plt");
2651 /* PLT is different on different platforms, it seems. */
2652 # if defined(VGP_x86_linux) || defined(VGP_amd64_linux) \
2653 || defined(VGP_arm_linux) || defined (VGP_s390x_linux) \
2654 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
2655 || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
2656 || defined(VGP_x86_solaris) || defined(VGP_amd64_solaris) \
2657 || defined(VGP_x86_freebsd) || defined(VGP_amd64_freebsd)
2658 /* Accept .plt where mapped as rx (code) */
2659 if (0 == VG_(strcmp)(name, ".plt")) {
2660 if (inrx && !di->plt_present) {
2661 di->plt_present = True;
2662 di->plt_avma = svma + inrx->bias;
2663 di->plt_size = size;
2664 TRACE_SYMTAB("acquiring .plt avma = %#lx\n", di->plt_avma);
2665 } else {
2666 BAD(".plt");
2669 # elif defined(VGP_ppc32_linux)
2670 /* Accept .plt where mapped as rw (data) */
2671 if (0 == VG_(strcmp)(name, ".plt")) {
2672 if (inrw1 && !di->plt_present) {
2673 di->plt_present = True;
2674 di->plt_avma = svma + inrw1->bias;
2675 di->plt_size = size;
2676 TRACE_SYMTAB("acquiring .plt avma = %#lx\n", di->plt_avma);
2677 } else {
2678 BAD(".plt");
2681 # elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
2682 /* Accept .plt where mapped as rw (data), or unmapped */
2683 if (0 == VG_(strcmp)(name, ".plt")) {
2684 if (inrw1 && !di->plt_present) {
2685 di->plt_present = True;
2686 di->plt_avma = svma + inrw1->bias;
2687 di->plt_size = size;
2688 TRACE_SYMTAB("acquiring .plt avma = %#lx\n", di->plt_avma);
2689 } else
2690 if ((!inrw1) && (!inrx) && size > 0 && !di->plt_present) {
2691 /* File contains a .plt, but it didn't get mapped.
2692 Presumably it is not required on this platform. At
2693 least don't reject the situation as invalid. */
2694 di->plt_present = True;
2695 di->plt_avma = 0;
2696 di->plt_size = 0;
2697 } else {
2698 BAD(".plt");
2701 # else
2702 # error "Unsupported platform"
2703 # endif
2705 /* Accept .opd where mapped as rw (data) */
2706 if (0 == VG_(strcmp)(name, ".opd")) {
2707 if (inrw1 && !di->opd_present) {
2708 di->opd_present = True;
2709 di->opd_avma = svma + inrw1->bias;
2710 di->opd_size = size;
2711 TRACE_SYMTAB("acquiring .opd avma = %#lx\n", di->opd_avma);
2712 } else {
2713 BAD(".opd");
2717 /* Accept .eh_frame where mapped as rx (code). This seems to be
2718 the common case. However, if that doesn't pan out, try for
2719 rw (data) instead. We can handle up to N_EHFRAME_SECTS per
2720 ELF object. */
2721 if (0 == VG_(strcmp)(name, ".eh_frame")) {
2722 if (inrx && di->n_ehframe < N_EHFRAME_SECTS) {
2723 di->ehframe_avma[di->n_ehframe] = svma + inrx->bias;
2724 di->ehframe_size[di->n_ehframe] = size;
2725 TRACE_SYMTAB("acquiring .eh_frame avma = %#lx\n",
2726 di->ehframe_avma[di->n_ehframe]);
2727 di->n_ehframe++;
2728 } else
2729 if (inrw1 && di->n_ehframe < N_EHFRAME_SECTS) {
2730 di->ehframe_avma[di->n_ehframe] = svma + inrw1->bias;
2731 di->ehframe_size[di->n_ehframe] = size;
2732 TRACE_SYMTAB("acquiring .eh_frame avma = %#lx\n",
2733 di->ehframe_avma[di->n_ehframe]);
2734 di->n_ehframe++;
2735 } else {
2736 BAD(".eh_frame");
2740 /* Accept .ARM.exidx where mapped as rx (code). */
2741 /* FIXME: make sure the entire section is mapped in, not just
2742 the first address. */
2743 if (0 == VG_(strcmp)(name, ".ARM.exidx")) {
2744 if (inrx && !di->exidx_present) {
2745 di->exidx_present = True;
2746 di->exidx_svma = svma;
2747 di->exidx_avma = svma + inrx->bias;
2748 di->exidx_size = size;
2749 di->exidx_bias = inrx->bias;
2750 TRACE_SYMTAB("acquiring .exidx svma = %#lx .. %#lx\n",
2751 di->exidx_svma,
2752 di->exidx_svma + di->exidx_size - 1);
2753 TRACE_SYMTAB("acquiring .exidx avma = %#lx .. %#lx\n",
2754 di->exidx_avma,
2755 di->exidx_avma + di->exidx_size - 1);
2756 TRACE_SYMTAB("acquiring .exidx bias = %#lx\n",
2757 (UWord)di->exidx_bias);
2758 } else {
2759 BAD(".ARM.exidx");
2763 /* Accept .ARM.extab where mapped as rx (code). */
2764 /* FIXME: make sure the entire section is mapped in, not just
2765 the first address. */
2766 if (0 == VG_(strcmp)(name, ".ARM.extab")) {
2767 if (inrx && !di->extab_present) {
2768 di->extab_present = True;
2769 di->extab_svma = svma;
2770 di->extab_avma = svma + inrx->bias;
2771 di->extab_size = size;
2772 di->extab_bias = inrx->bias;
2773 TRACE_SYMTAB("acquiring .extab svma = %#lx .. %#lx\n",
2774 di->extab_svma,
2775 di->extab_svma + di->extab_size - 1);
2776 TRACE_SYMTAB("acquiring .extab avma = %#lx .. %#lx\n",
2777 di->extab_avma,
2778 di->extab_avma + di->extab_size - 1);
2779 TRACE_SYMTAB("acquiring .extab bias = %#lx\n",
2780 (UWord)di->extab_bias);
2781 } else {
2782 BAD(".ARM.extab");
2786 ML_(dinfo_free)(name);
2788 # undef BAD
2790 } /* iterate over the section headers */
2792 /* TOPLEVEL */
2793 if (0) VG_(printf)("YYYY text_: avma %#lx size %lu bias %#lx\n",
2794 di->text_avma, di->text_size, (UWord)di->text_bias);
2796 if (VG_(clo_verbosity) > 2 || VG_(clo_trace_redir))
2797 VG_(message)(Vg_DebugMsg, " svma %#010lx, avma %#010lx\n",
2798 di->text_avma - di->text_bias,
2799 di->text_avma );
2801 TRACE_SYMTAB("\n");
2802 TRACE_SYMTAB("------ Finding image addresses "
2803 "for debug-info sections ------\n");
2805 /* TOPLEVEL */
2806 /* Find interesting sections, read the symbol table(s), read any
2807 debug information. Each section is located either in the main,
2808 debug or alt-debug files, but only in one. For each section,
2809 |section_escn| records which of |mimg|, |dimg| or |aimg| we
2810 found it in, along with the section's image offset and its size.
2811 The triples (section_img, section_ioff, section_szB) are
2812 consistent, in that they are always either (NULL,
2813 DiOffT_INVALID, 0), or refer to the same image, and are all
2814 assigned together. */
2816 /* TOPLEVEL */
2817 DiSlice strtab_escn = DiSlice_INVALID; // .strtab
2818 DiSlice symtab_escn = DiSlice_INVALID; // .symtab
2819 DiSlice dynstr_escn = DiSlice_INVALID; // .dynstr
2820 DiSlice dynsym_escn = DiSlice_INVALID; // .dynsym
2821 # if defined(VGO_solaris)
2822 DiSlice ldynsym_escn = DiSlice_INVALID; // .SUNW_ldynsym
2823 # endif
2824 DiSlice debuglink_escn = DiSlice_INVALID; // .gnu_debuglink
2825 DiSlice debugaltlink_escn = DiSlice_INVALID; // .gnu_debugaltlink
2826 DiSlice debug_line_escn = DiSlice_INVALID; // .debug_line (dwarf2)
2827 DiSlice debug_info_escn = DiSlice_INVALID; // .debug_info (dwarf2)
2828 DiSlice debug_types_escn = DiSlice_INVALID; // .debug_types (dwarf4)
2829 DiSlice debug_abbv_escn = DiSlice_INVALID; // .debug_abbrev (dwarf2)
2830 DiSlice debug_str_escn = DiSlice_INVALID; // .debug_str (dwarf2)
2831 DiSlice debug_line_str_escn = DiSlice_INVALID; // .debug_line_str(dwarf5)
2832 DiSlice debug_ranges_escn = DiSlice_INVALID; // .debug_ranges (dwarf2)
2833 DiSlice debug_rnglists_escn = DiSlice_INVALID; // .debug_rnglists(dwarf5)
2834 DiSlice debug_loclists_escn = DiSlice_INVALID; // .debug_loclists(dwarf5)
2835 DiSlice debug_addr_escn = DiSlice_INVALID; // .debug_addr (dwarf5)
2836 DiSlice debug_str_offsets_escn = DiSlice_INVALID; // .debug_str_offsets (dwarf5)
2837 DiSlice debug_loc_escn = DiSlice_INVALID; // .debug_loc (dwarf2)
2838 DiSlice debug_frame_escn = DiSlice_INVALID; // .debug_frame (dwarf2)
2839 DiSlice debug_line_alt_escn = DiSlice_INVALID; // .debug_line (alt)
2840 DiSlice debug_info_alt_escn = DiSlice_INVALID; // .debug_info (alt)
2841 DiSlice debug_abbv_alt_escn = DiSlice_INVALID; // .debug_abbrev (alt)
2842 DiSlice debug_str_alt_escn = DiSlice_INVALID; // .debug_str (alt)
2843 DiSlice dwarf1d_escn = DiSlice_INVALID; // .debug (dwarf1)
2844 DiSlice dwarf1l_escn = DiSlice_INVALID; // .line (dwarf1)
2845 DiSlice opd_escn = DiSlice_INVALID; // .opd (dwarf2,
2846 // ppc64be-linux)
2847 DiSlice ehframe_escn[N_EHFRAME_SECTS]; // .eh_frame (dwarf2)
2849 for (i = 0; i < N_EHFRAME_SECTS; i++)
2850 ehframe_escn[i] = DiSlice_INVALID;
2852 /* Find all interesting sections */
2854 UInt ehframe_mix = 0;
2856 /* What FIND does: it finds the section called _SEC_NAME. The
2857 size of it is assigned to _SEC_SIZE. The address of the
2858 section in the transiently loaded oimage is assigned to
2859 _SEC_IMG. If the section is found, _POST_FX is executed
2860 after _SEC_NAME and _SEC_SIZE have been assigned to.
2862 Even for sections which are marked loadable, the client's
2863 ld.so may not have loaded them yet, so there is no guarantee
2864 that we can safely prod around in any such area). Because
2865 the entire object file is transiently mapped aboard for
2866 inspection, it's always safe to inspect that area. */
2868 /* TOPLEVEL */
2869 /* Iterate over section headers (again) */
2870 for (i = 0; i < ehdr_m.e_shnum; i++) {
2872 # define FINDX(_sec_name, _sec_escn, _post_fx) \
2873 do { \
2874 ElfXX_Shdr a_shdr; \
2875 ML_(img_get)(&a_shdr, mimg, \
2876 INDEX_BIS(shdr_mioff, i, shdr_ment_szB), \
2877 sizeof(a_shdr)); \
2878 if (0 == ML_(img_strcmp_c)(mimg, shdr_strtab_mioff \
2879 + a_shdr.sh_name, _sec_name)) { \
2880 Bool nobits; \
2881 _sec_escn.img = mimg; \
2882 _sec_escn.ioff = (DiOffT)a_shdr.sh_offset; \
2883 _sec_escn.szB = a_shdr.sh_size; \
2884 if (!check_compression(&a_shdr, &_sec_escn)) { \
2885 ML_(symerr)(di, True, " Compression type is unsupported"); \
2886 goto out; \
2888 nobits = a_shdr.sh_type == SHT_NOBITS; \
2889 vg_assert(_sec_escn.img != NULL); \
2890 vg_assert(_sec_escn.ioff != DiOffT_INVALID); \
2891 TRACE_SYMTAB( "%-18s: ioff %llu .. %llu\n", \
2892 _sec_name, (ULong)a_shdr.sh_offset, \
2893 ((ULong)a_shdr.sh_offset) + a_shdr.sh_size - 1); \
2894 /* SHT_NOBITS sections have zero size in the file. */ \
2895 if (!nobits && \
2896 a_shdr.sh_offset + \
2897 a_shdr.sh_size > ML_(img_real_size)(mimg)) { \
2898 ML_(symerr)(di, True, \
2899 " section beyond image end?!"); \
2900 goto out; \
2902 _post_fx; \
2904 } while (0);
2906 /* Version with no post-effects */
2907 # define FIND(_sec_name, _sec_escn) \
2908 FINDX(_sec_name, _sec_escn, /**/)
2910 /* NAME ElfSec */
2911 FIND( ".dynsym", dynsym_escn)
2912 FIND( ".dynstr", dynstr_escn)
2913 FIND( ".symtab", symtab_escn)
2914 FIND( ".strtab", strtab_escn)
2915 # if defined(VGO_solaris)
2916 FIND( ".SUNW_ldynsym", ldynsym_escn)
2917 # endif
2919 FIND( ".gnu_debuglink", debuglink_escn)
2920 FIND( ".gnu_debugaltlink", debugaltlink_escn)
2922 FIND( ".debug_line", debug_line_escn)
2923 if (!ML_(sli_is_valid)(debug_line_escn))
2924 FIND(".zdebug_line", debug_line_escn)
2926 FIND( ".debug_info", debug_info_escn)
2927 if (!ML_(sli_is_valid)(debug_info_escn))
2928 FIND(".zdebug_info", debug_info_escn)
2930 FIND( ".debug_types", debug_types_escn)
2931 if (!ML_(sli_is_valid)(debug_types_escn))
2932 FIND(".zdebug_types", debug_types_escn)
2934 FIND( ".debug_abbrev", debug_abbv_escn)
2935 if (!ML_(sli_is_valid)(debug_abbv_escn))
2936 FIND(".zdebug_abbrev", debug_abbv_escn)
2938 FIND( ".debug_str", debug_str_escn)
2939 if (!ML_(sli_is_valid)(debug_str_escn))
2940 FIND(".zdebug_str", debug_str_escn)
2942 FIND( ".debug_line_str", debug_line_str_escn)
2943 if (!ML_(sli_is_valid)(debug_line_str_escn))
2944 FIND(".zdebug_str", debug_line_str_escn)
2946 FIND( ".debug_ranges", debug_ranges_escn)
2947 if (!ML_(sli_is_valid)(debug_ranges_escn))
2948 FIND(".zdebug_ranges", debug_ranges_escn)
2950 FIND( ".debug_rnglists", debug_rnglists_escn)
2951 if (!ML_(sli_is_valid)(debug_rnglists_escn))
2952 FIND(".zdebug_rnglists", debug_rnglists_escn)
2954 FIND( ".debug_loclists", debug_loclists_escn)
2955 if (!ML_(sli_is_valid)(debug_loclists_escn))
2956 FIND(".zdebug_loclists", debug_loclists_escn)
2958 FIND( ".debug_loc", debug_loc_escn)
2959 if (!ML_(sli_is_valid)(debug_loc_escn))
2960 FIND(".zdebug_loc", debug_loc_escn)
2962 FIND( ".debug_frame", debug_frame_escn)
2963 if (!ML_(sli_is_valid)(debug_frame_escn))
2964 FIND(".zdebug_frame", debug_frame_escn)
2966 FIND( ".debug_addr", debug_addr_escn)
2967 if (!ML_(sli_is_valid)(debug_addr_escn))
2968 FIND(".zdebug_addr", debug_addr_escn)
2970 FIND( ".debug_str_offsets", debug_str_offsets_escn)
2971 if (!ML_(sli_is_valid)(debug_str_offsets_escn))
2972 FIND(".zdebug_str_offsets", debug_str_offsets_escn)
2974 FIND( ".debug", dwarf1d_escn)
2975 FIND( ".line", dwarf1l_escn)
2977 FIND( ".opd", opd_escn)
2979 FINDX( ".eh_frame", ehframe_escn[ehframe_mix],
2980 do { ehframe_mix++; vg_assert(ehframe_mix <= N_EHFRAME_SECTS);
2981 } while (0)
2983 /* Comment_on_EH_FRAME_MULTIPLE_INSTANCES: w.r.t. .eh_frame
2984 multi-instance kludgery, how are we assured that the order
2985 in which we fill in ehframe_escn[] is consistent with the
2986 order in which we previously filled in di->ehframe_avma[]
2987 and di->ehframe_size[] ? By the fact that in both cases,
2988 these arrays were filled in by iterating over the section
2989 headers top-to-bottom. So both loops (this one and the
2990 previous one) encounter the .eh_frame entries in the same
2991 order and so fill in these arrays in a consistent order.
2994 # undef FINDX
2995 # undef FIND
2996 } /* Iterate over section headers (again) */
2998 /* TOPLEVEL */
2999 /* Now, see if we can find a debuginfo object, and if so connect
3000 |dimg| to it. */
3001 vg_assert(dimg == NULL && aimg == NULL);
3003 #if defined(VGO_freebsd)
3004 /* */
3005 read_and_set_osrel(mimg);
3007 #endif
3009 /* Look for a build-id */
3010 HChar* buildid = find_buildid(mimg, False, False);
3012 /* If we don't have a .debug_info section in the main image then
3013 look for a debug image that matches either the build-id or
3014 the debuglink-CRC32 in the main image. If the main image
3015 doesn't contain either of those then this won't even bother
3016 to try looking. This looks in all known places, including
3017 the --extra-debuginfo-path if specified and on the
3018 --debuginfo-server if specified. */
3019 if (debug_info_escn.img == NULL &&
3020 (buildid != NULL || debuglink_escn.img != NULL)) {
3021 /* Do have a debuglink section? */
3022 if (debuglink_escn.img != NULL) {
3023 UInt crc_offset
3024 = VG_ROUNDUP(ML_(img_strlen)(debuglink_escn.img,
3025 debuglink_escn.ioff)+1, 4);
3026 vg_assert(crc_offset + sizeof(UInt) <= debuglink_escn.szB);
3028 /* Extract the CRC from the debuglink section */
3029 UInt crc = ML_(img_get_UInt)(debuglink_escn.img,
3030 debuglink_escn.ioff + crc_offset);
3032 /* See if we can find a matching debug file */
3033 HChar* debuglink_str_m
3034 = ML_(img_strdup)(debuglink_escn.img,
3035 "di.redi_dlk.1", debuglink_escn.ioff);
3036 dimg = find_debug_file( di, di->fsm.filename, buildid,
3037 debuglink_str_m, crc, False );
3038 if (debuglink_str_m)
3039 ML_(dinfo_free)(debuglink_str_m);
3040 } else {
3041 /* See if we can find a matching debug file */
3042 dimg = find_debug_file( di, di->fsm.filename, buildid,
3043 NULL, 0, False );
3047 if (buildid) {
3048 ML_(dinfo_free)(buildid);
3049 buildid = NULL; /* paranoia */
3052 /* As a last-ditch measure, try looking for in the
3053 --extra-debuginfo-path and/or on the --debuginfo-server, but
3054 only in the case where --allow-mismatched-debuginfo=yes.
3055 This is dangerous in that (1) it gives no assurance that the
3056 debuginfo object matches the main one, and hence (2) we will
3057 very likely get an assertion in the code below, if indeed
3058 there is a mismatch. Hence it is disabled by default
3059 (--allow-mismatched-debuginfo=no). Nevertheless it's
3060 sometimes a useful way of getting out of a tight spot.
3062 Note that we're ignoring the name in the .gnu_debuglink
3063 section here, and just looking for a file of the same name
3064 either the extra-path or on the server. */
3065 if (dimg == NULL && VG_(clo_allow_mismatched_debuginfo)) {
3066 dimg = find_debug_file_ad_hoc( di, di->fsm.filename );
3069 /* TOPLEVEL */
3070 /* If we were successful in finding a debug image, pull various
3071 SVMA/bias/size and image addresses out of it. */
3072 if (dimg != NULL && is_elf_object_file_by_DiImage(dimg, False)) {
3074 /* Pull out and validate program header and section header info */
3075 DiOffT ehdr_dioff = 0;
3076 ElfXX_Ehdr ehdr_dimg;
3077 ML_(img_get)(&ehdr_dimg, dimg, ehdr_dioff, sizeof(ehdr_dimg));
3079 DiOffT phdr_dioff = ehdr_dimg.e_phoff;
3080 UWord phdr_dnent = ehdr_dimg.e_phnum;
3081 UWord phdr_dent_szB = ehdr_dimg.e_phentsize;
3083 DiOffT shdr_dioff = ehdr_dimg.e_shoff;
3084 UWord shdr_dnent = ehdr_dimg.e_shnum;
3085 UWord shdr_dent_szB = ehdr_dimg.e_shentsize;
3087 DiOffT shdr_strtab_dioff = DiOffT_INVALID;
3089 /* SVMAs covered by rx and rw segments and corresponding bias. */
3090 Addr rx_dsvma_limit = 0;
3091 PtrdiffT rx_dbias = 0;
3092 Addr rw_dsvma_limit = 0;
3093 PtrdiffT rw_dbias = 0;
3095 Bool need_symtab, need_dwarf2, need_dwarf1;
3097 if (phdr_dnent == 0
3098 || !ML_(img_valid)(dimg, phdr_dioff,
3099 phdr_dnent * phdr_dent_szB)) {
3100 ML_(symerr)(di, True,
3101 "Missing or invalid ELF Program Header Table"
3102 " (debuginfo file)");
3103 goto out;
3106 if (shdr_dnent == 0
3107 || !ML_(img_valid)(dimg, shdr_dioff,
3108 shdr_dnent * shdr_dent_szB)) {
3109 ML_(symerr)(di, True,
3110 "Missing or invalid ELF Section Header Table"
3111 " (debuginfo file)");
3112 goto out;
3115 /* Also find the section header's string table, and validate. */
3116 /* checked previously by is_elf_object_file: */
3117 vg_assert(ehdr_dimg.e_shstrndx != SHN_UNDEF);
3119 // shdr_dioff is the offset of the section header table
3120 // and we need the ehdr_dimg.e_shstrndx'th entry
3121 { ElfXX_Shdr a_shdr;
3122 ML_(img_get)(&a_shdr, dimg,
3123 INDEX_BIS(shdr_dioff, ehdr_dimg.e_shstrndx,
3124 shdr_dent_szB),
3125 sizeof(a_shdr));
3126 shdr_strtab_dioff = a_shdr.sh_offset;
3127 if (!ML_(img_valid)(dimg, shdr_strtab_dioff,
3128 1/*bogus, but we don't know the real size*/)) {
3129 ML_(symerr)(di, True,
3130 "Invalid ELF Section Header String Table"
3131 " (debuginfo file)");
3132 goto out;
3136 for (i = 0; i < ehdr_dimg.e_phnum; i++) {
3137 ElfXX_Phdr a_phdr;
3138 ML_(img_get)(&a_phdr, dimg, INDEX_BIS(ehdr_dimg.e_phoff,
3139 i, phdr_dent_szB),
3140 sizeof(a_phdr));
3141 if (a_phdr.p_type == PT_LOAD) {
3142 for (j = 0; j < VG_(sizeXA)(di->fsm.maps); j++) {
3143 const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, j);
3144 if ( a_phdr.p_offset >= map->foff
3145 && a_phdr.p_offset < map->foff + map->size
3146 && a_phdr.p_offset + a_phdr.p_filesz
3147 < map->foff + map->size) {
3148 if (map->rx && rx_dsvma_limit == 0) {
3149 rx_dsvma_limit = a_phdr.p_vaddr + a_phdr.p_memsz;
3150 rx_dbias = map->avma - map->foff + a_phdr.p_offset
3151 - a_phdr.p_vaddr;
3153 if (map->rw && rw_dsvma_limit == 0) {
3154 rw_dsvma_limit = a_phdr.p_vaddr + a_phdr.p_memsz;
3155 rw_dbias = map->avma - map->foff + a_phdr.p_offset
3156 - a_phdr.p_vaddr;
3158 break;
3164 need_symtab = (symtab_escn.img == NULL);
3165 need_dwarf2 = (debug_info_escn.img == NULL);
3166 need_dwarf1 = (dwarf1d_escn.img == NULL);
3168 /* Find all interesting sections in the debug image */
3169 for (i = 0; i < ehdr_dimg.e_shnum; i++) {
3171 /* Find debug svma and bias information for sections
3172 we found in the main file. */
3174 # define FIND(_sec, _seg) \
3175 do { \
3176 ElfXX_Shdr a_shdr; \
3177 ML_(img_get)(&a_shdr, dimg, \
3178 INDEX_BIS(shdr_dioff, i, shdr_dent_szB), \
3179 sizeof(a_shdr)); \
3180 if (di->_sec##_present \
3181 && 0 == ML_(img_strcmp_c)(dimg, shdr_strtab_dioff \
3182 + a_shdr.sh_name, "." #_sec)) { \
3183 vg_assert(di->_sec##_size == a_shdr.sh_size); \
3184 /* JRS 2013-Jun-01: the following assert doesn't contain */ \
3185 /* any ==s, which seems to me to be suspicious. */ \
3186 vg_assert(di->_sec##_avma + a_shdr.sh_addr + _seg##_dbias); \
3187 /* Assume we have a correct value for the main */ \
3188 /* object's bias. Use that to derive the debuginfo */ \
3189 /* object's bias, by adding the difference in SVMAs */ \
3190 /* for the corresponding sections in the two files. */ \
3191 /* That should take care of all prelinking effects. */ \
3192 di->_sec##_debug_svma = a_shdr.sh_addr; \
3193 di->_sec##_debug_bias \
3194 = di->_sec##_bias + \
3195 di->_sec##_svma - di->_sec##_debug_svma; \
3196 TRACE_SYMTAB("acquiring ." #_sec \
3197 " debug svma = %#lx .. %#lx\n", \
3198 di->_sec##_debug_svma, \
3199 di->_sec##_debug_svma + di->_sec##_size - 1); \
3200 TRACE_SYMTAB("acquiring ." #_sec " debug bias = %#lx\n", \
3201 (UWord)di->_sec##_debug_bias); \
3203 } while (0);
3205 /* SECTION SEGMENT */
3206 FIND(text, rx)
3207 FIND(data, rw)
3208 FIND(sdata, rw)
3209 FIND(rodata, rw)
3210 FIND(bss, rw)
3211 FIND(sbss, rw)
3213 # undef FIND
3215 /* Same deal as previous FIND, except only do it for those
3216 sections which we didn't find in the main file. */
3218 # define FIND(_condition, _sec_name, _sec_escn) \
3219 do { \
3220 ElfXX_Shdr a_shdr; \
3221 ML_(img_get)(&a_shdr, dimg, \
3222 INDEX_BIS(shdr_dioff, i, shdr_dent_szB), \
3223 sizeof(a_shdr)); \
3224 if (_condition \
3225 && 0 == ML_(img_strcmp_c)(dimg, shdr_strtab_dioff \
3226 + a_shdr.sh_name, _sec_name)) { \
3227 Bool nobits; \
3228 if (_sec_escn.img != NULL) { \
3229 ML_(symerr)(di, True, \
3230 " debuginfo section duplicates a" \
3231 " section in the main ELF file"); \
3232 goto out; \
3234 _sec_escn.img = dimg; \
3235 _sec_escn.ioff = (DiOffT)a_shdr.sh_offset; \
3236 _sec_escn.szB = a_shdr.sh_size; \
3237 if (!check_compression(&a_shdr, &_sec_escn)) { \
3238 ML_(symerr)(di, True, " Compression type is unsupported"); \
3239 goto out; \
3241 nobits = a_shdr.sh_type == SHT_NOBITS; \
3242 vg_assert(_sec_escn.img != NULL); \
3243 vg_assert(_sec_escn.ioff != DiOffT_INVALID); \
3244 TRACE_SYMTAB( "%-18s: dioff %llu .. %llu\n", \
3245 _sec_name, \
3246 (ULong)a_shdr.sh_offset, \
3247 ((ULong)a_shdr.sh_offset) + a_shdr.sh_size - 1); \
3248 /* SHT_NOBITS sections have zero size in the file. */ \
3249 if (!nobits && a_shdr.sh_offset \
3250 + a_shdr.sh_size > ML_(img_real_size)(_sec_escn.img)) { \
3251 ML_(symerr)(di, True, \
3252 " section beyond image end?!"); \
3253 goto out; \
3256 } while (0);
3258 /* NEEDED? NAME ElfSec */
3259 FIND( need_symtab, ".symtab", symtab_escn)
3260 FIND( need_symtab, ".strtab", strtab_escn)
3261 FIND( need_dwarf2, ".debug_line", debug_line_escn)
3262 if (!ML_(sli_is_valid)(debug_line_escn))
3263 FIND(need_dwarf2, ".zdebug_line", debug_line_escn)
3265 FIND( need_dwarf2, ".debug_info", debug_info_escn)
3266 if (!ML_(sli_is_valid)(debug_info_escn))
3267 FIND(need_dwarf2, ".zdebug_info", debug_info_escn)
3269 FIND( need_dwarf2, ".debug_types", debug_types_escn)
3270 if (!ML_(sli_is_valid)(debug_types_escn))
3271 FIND(need_dwarf2, ".zdebug_types", debug_types_escn)
3273 FIND( need_dwarf2, ".debug_abbrev", debug_abbv_escn)
3274 if (!ML_(sli_is_valid)(debug_abbv_escn))
3275 FIND(need_dwarf2, ".zdebug_abbrev", debug_abbv_escn)
3277 FIND( need_dwarf2, ".debug_str", debug_str_escn)
3278 if (!ML_(sli_is_valid)(debug_str_escn))
3279 FIND(need_dwarf2, ".zdebug_str", debug_str_escn)
3281 FIND( need_dwarf2, ".debug_line_str", debug_line_str_escn)
3282 if (!ML_(sli_is_valid)(debug_line_str_escn))
3283 FIND(need_dwarf2, ".zdebug_line_str", debug_line_str_escn)
3285 FIND( need_dwarf2, ".debug_ranges", debug_ranges_escn)
3286 if (!ML_(sli_is_valid)(debug_ranges_escn))
3287 FIND(need_dwarf2, ".zdebug_ranges", debug_ranges_escn)
3289 FIND( need_dwarf2, ".debug_rnglists", debug_rnglists_escn)
3290 if (!ML_(sli_is_valid)(debug_rnglists_escn))
3291 FIND(need_dwarf2, ".zdebug_rnglists", debug_rnglists_escn)
3293 FIND( need_dwarf2, ".debug_loclists", debug_loclists_escn)
3294 if (!ML_(sli_is_valid)(debug_loclists_escn))
3295 FIND(need_dwarf2, ".zdebug_loclists", debug_loclists_escn)
3297 FIND( need_dwarf2, ".debug_loc", debug_loc_escn)
3298 if (!ML_(sli_is_valid)(debug_loc_escn))
3299 FIND(need_dwarf2, ".zdebug_loc", debug_loc_escn)
3301 FIND( need_dwarf2, ".debug_frame", debug_frame_escn)
3302 if (!ML_(sli_is_valid)(debug_frame_escn))
3303 FIND(need_dwarf2, ".zdebug_frame", debug_frame_escn)
3305 FIND( need_dwarf2, ".debug_addr", debug_addr_escn)
3306 if (!ML_(sli_is_valid)(debug_addr_escn))
3307 FIND(need_dwarf2, ".zdebug_addr", debug_addr_escn)
3309 FIND( need_dwarf2, ".debug_str_offsets", debug_str_offsets_escn)
3310 if (!ML_(sli_is_valid)(debug_str_offsets_escn))
3311 FIND(need_dwarf2, ".zdebug_str_offsets", debug_str_offsets_escn)
3313 if (!ML_(sli_is_valid)(debugaltlink_escn))
3314 FIND( need_dwarf2, ".gnu_debugaltlink", debugaltlink_escn)
3316 FIND( need_dwarf1, ".debug", dwarf1d_escn)
3317 FIND( need_dwarf1, ".line", dwarf1l_escn)
3319 # undef FIND
3320 } /* Find all interesting sections */
3321 } /* do we have a debug image? */
3323 /* TOPLEVEL */
3324 /* Look for alternate debug image, and if found, connect |aimg|
3325 to it. */
3326 vg_assert(aimg == NULL);
3328 if (debugaltlink_escn.img != NULL) {
3329 HChar* altfile_str_m
3330 = ML_(img_strdup)(debugaltlink_escn.img,
3331 "di.fbi.3", debugaltlink_escn.ioff);
3332 UInt buildid_offset = ML_(img_strlen)(debugaltlink_escn.img,
3333 debugaltlink_escn.ioff)+1;
3335 vg_assert(buildid_offset < debugaltlink_escn.szB);
3337 HChar *altbuildid
3338 = ML_(dinfo_zalloc)("di.fbi.4",
3339 (debugaltlink_escn.szB - buildid_offset)
3340 * 2 + 1);
3342 /* The altfile might be relative to the debug file or main file.
3343 Make sure that we got the real file, not a symlink. */
3344 HChar *dbgname = di->fsm.dbgname ? di->fsm.dbgname : di->fsm.filename;
3345 HChar* rdbgname = readlink_path (dbgname);
3346 if (rdbgname == NULL)
3347 rdbgname = ML_(dinfo_strdup)("rdbgname", dbgname);
3349 for (j = 0; j < debugaltlink_escn.szB - buildid_offset; j++)
3350 VG_(sprintf)(
3351 altbuildid + 2 * j, "%02x",
3352 (UInt)ML_(img_get_UChar)(debugaltlink_escn.img,
3353 debugaltlink_escn.ioff
3354 + buildid_offset + j));
3356 /* See if we can find a matching debug file */
3357 aimg = find_debug_file( di, rdbgname, altbuildid,
3358 altfile_str_m, 0, True );
3360 ML_(dinfo_free)(rdbgname);
3362 if (altfile_str_m)
3363 ML_(dinfo_free)(altfile_str_m);
3364 ML_(dinfo_free)(altbuildid);
3367 /* TOPLEVEL */
3368 /* If we were successful in finding alternate debug image, pull various
3369 size and image addresses out of it. */
3370 if (aimg != NULL && is_elf_object_file_by_DiImage(aimg, True)) {
3372 /* Pull out and validate program header and section header info */
3373 DiOffT ehdr_aioff = 0;
3374 ElfXX_Ehdr ehdr_aimg;
3375 ML_(img_get)(&ehdr_aimg, aimg, ehdr_aioff, sizeof(ehdr_aimg));
3377 DiOffT shdr_aioff = ehdr_aimg.e_shoff;
3378 UWord shdr_anent = ehdr_aimg.e_shnum;
3379 UWord shdr_aent_szB = ehdr_aimg.e_shentsize;
3381 DiOffT shdr_strtab_aioff = DiOffT_INVALID;
3383 if (shdr_anent == 0
3384 || !ML_(img_valid)(aimg, shdr_aioff,
3385 shdr_anent * shdr_aent_szB)) {
3386 ML_(symerr)(di, True,
3387 "Missing or invalid ELF Section Header Table"
3388 " (alternate debuginfo file)");
3389 goto out;
3392 /* Also find the section header's string table, and validate. */
3393 /* checked previously by is_elf_object_file: */
3394 vg_assert(ehdr_aimg.e_shstrndx != SHN_UNDEF);
3396 // shdr_aioff is the offset of the section header table
3397 // and we need the ehdr_aimg.e_shstrndx'th entry
3398 { ElfXX_Shdr a_shdr;
3399 ML_(img_get)(&a_shdr, aimg,
3400 INDEX_BIS(shdr_aioff, ehdr_aimg.e_shstrndx,
3401 shdr_aent_szB),
3402 sizeof(a_shdr));
3403 shdr_strtab_aioff = a_shdr.sh_offset;
3404 if (!ML_(img_valid)(aimg, shdr_strtab_aioff,
3405 1/*bogus, but we don't know the real size*/)) {
3406 ML_(symerr)(di, True,
3407 "Invalid ELF Section Header String Table"
3408 " (alternate debuginfo file)");
3409 goto out;
3413 /* Find all interesting sections */
3414 for (i = 0; i < ehdr_aimg.e_shnum; i++) {
3416 # define FIND(_sec_name, _sec_escn) \
3417 do { \
3418 ElfXX_Shdr a_shdr; \
3419 ML_(img_get)(&a_shdr, aimg, \
3420 INDEX_BIS(shdr_aioff, i, shdr_aent_szB), \
3421 sizeof(a_shdr)); \
3422 if (0 == ML_(img_strcmp_c)(aimg, shdr_strtab_aioff \
3423 + a_shdr.sh_name, _sec_name)) { \
3424 if (_sec_escn.img != NULL) { \
3425 ML_(symerr)(di, True, \
3426 " alternate debuginfo section duplicates a" \
3427 " section in the main ELF file"); \
3428 goto out; \
3430 _sec_escn.img = aimg; \
3431 _sec_escn.ioff = (DiOffT)a_shdr.sh_offset; \
3432 _sec_escn.szB = a_shdr.sh_size; \
3433 if (!check_compression(&a_shdr, &_sec_escn)) { \
3434 ML_(symerr)(di, True, " Compression type is " \
3435 "unsupported"); \
3436 goto out; \
3438 vg_assert(_sec_escn.img != NULL); \
3439 vg_assert(_sec_escn.ioff != DiOffT_INVALID); \
3440 TRACE_SYMTAB( "%-18s: aioff %llu .. %llu\n", \
3441 _sec_name, \
3442 (ULong)a_shdr.sh_offset, \
3443 ((ULong)a_shdr.sh_offset) + a_shdr.sh_size - 1); \
3445 } while (0);
3447 /* NAME ElfSec */
3448 FIND(".debug_line", debug_line_alt_escn)
3449 if (!ML_(sli_is_valid)(debug_line_alt_escn))
3450 FIND(".zdebug_line", debug_line_alt_escn)
3452 FIND(".debug_info", debug_info_alt_escn)
3453 if (!ML_(sli_is_valid)(debug_info_alt_escn))
3454 FIND(".zdebug_info", debug_info_alt_escn)
3456 FIND(".debug_abbrev", debug_abbv_alt_escn)
3457 if (!ML_(sli_is_valid)(debug_abbv_alt_escn))
3458 FIND(".zdebug_abbrev", debug_abbv_alt_escn)
3460 FIND(".debug_str", debug_str_alt_escn)
3461 if (!ML_(sli_is_valid)(debug_str_alt_escn))
3462 FIND(".zdebug_str", debug_str_alt_escn)
3464 # undef FIND
3465 } /* Find all interesting sections */
3466 } /* do we have a debug image? */
3469 /* TOPLEVEL */
3470 /* Check some sizes */
3471 vg_assert((dynsym_escn.szB % sizeof(ElfXX_Sym)) == 0);
3472 vg_assert((symtab_escn.szB % sizeof(ElfXX_Sym)) == 0);
3473 # if defined(VGO_solaris)
3474 vg_assert((ldynsym_escn.szB % sizeof(ElfXX_Sym)) == 0);
3475 # endif
3477 /* TOPLEVEL */
3478 /* Read symbols */
3480 void (*read_elf_symtab)(struct _DebugInfo*, const HChar*,
3481 DiSlice*, DiSlice*, DiSlice*, Bool);
3482 Bool symtab_in_debug;
3483 # if defined(VGP_ppc64be_linux)
3484 read_elf_symtab = read_elf_symtab__ppc64be_linux;
3485 # else
3486 read_elf_symtab = read_elf_symtab__normal;
3487 # endif
3488 symtab_in_debug = symtab_escn.img == dimg;
3489 read_elf_symtab(di, "symbol table",
3490 &symtab_escn, &strtab_escn, &opd_escn,
3491 symtab_in_debug);
3492 read_elf_symtab(di, "dynamic symbol table",
3493 &dynsym_escn, &dynstr_escn, &opd_escn,
3494 False);
3495 # if defined(VGO_solaris)
3496 read_elf_symtab(di, "local dynamic symbol table",
3497 &ldynsym_escn, &dynstr_escn, &opd_escn,
3498 False);
3499 # endif
3502 /* TOPLEVEL */
3503 /* Read .eh_frame and .debug_frame (call-frame-info) if any. Do
3504 the .eh_frame section(s) first. */
3505 vg_assert(di->n_ehframe >= 0 && di->n_ehframe <= N_EHFRAME_SECTS);
3506 for (i = 0; i < di->n_ehframe; i++) {
3507 /* see Comment_on_EH_FRAME_MULTIPLE_INSTANCES above for why
3508 this next assertion should hold. */
3509 vg_assert(ML_(sli_is_valid)(ehframe_escn[i]));
3510 vg_assert(ehframe_escn[i].szB == di->ehframe_size[i]);
3511 ML_(read_callframe_info_dwarf3)( di,
3512 ehframe_escn[i],
3513 di->ehframe_avma[i],
3514 True/*is_ehframe*/ );
3516 if (ML_(sli_is_valid)(debug_frame_escn)) {
3517 ML_(read_callframe_info_dwarf3)( di,
3518 debug_frame_escn,
3519 0/*assume zero avma*/,
3520 False/*!is_ehframe*/ );
3523 /* TOPLEVEL */
3524 /* jrs 2006-01-01: icc-8.1 has been observed to generate
3525 binaries without debug_str sections. Don't preclude
3526 debuginfo reading for that reason, but, in
3527 read_unitinfo_dwarf2, do check that debugstr is non-NULL
3528 before using it. */
3529 if (ML_(sli_is_valid)(debug_info_escn)
3530 && ML_(sli_is_valid)(debug_abbv_escn)
3531 && ML_(sli_is_valid)(debug_line_escn)) {
3532 /* The old reader: line numbers and unwind info only */
3533 ML_(read_debuginfo_dwarf3) ( di,
3534 debug_info_escn,
3535 debug_types_escn,
3536 debug_abbv_escn,
3537 debug_line_escn,
3538 debug_str_escn,
3539 debug_str_alt_escn,
3540 debug_line_str_escn);
3541 /* The new reader: read the DIEs in .debug_info to acquire
3542 information on variable types and locations or inline info.
3543 But only if the tool asks for it, or the user requests it on
3544 the command line. */
3545 if (VG_(clo_read_var_info) /* the user or tool asked for it */
3546 || VG_(clo_read_inline_info)) {
3547 ML_(new_dwarf3_reader)(
3548 di, debug_info_escn, debug_types_escn,
3549 debug_abbv_escn, debug_line_escn,
3550 debug_str_escn, debug_ranges_escn,
3551 debug_rnglists_escn, debug_loclists_escn,
3552 debug_loc_escn, debug_info_alt_escn,
3553 debug_abbv_alt_escn, debug_line_alt_escn,
3554 debug_str_alt_escn, debug_line_str_escn,
3555 debug_addr_escn, debug_str_offsets_escn
3560 /* TOPLEVEL */
3561 // JRS 31 July 2014: dwarf-1 reading is currently broken and
3562 // therefore deactivated.
3563 //if (dwarf1d_img && dwarf1l_img) {
3564 // ML_(read_debuginfo_dwarf1) ( di, dwarf1d_img, dwarf1d_sz,
3565 // dwarf1l_img, dwarf1l_sz );
3568 # if defined(VGA_arm)
3569 /* TOPLEVEL */
3570 /* ARM32 only: read .exidx/.extab if present. Note we are
3571 reading these directly out of the mapped in (running) image.
3572 Also, read these only if no CFI based unwind info was
3573 acquired for this file.
3575 An .exidx section is always required, but the .extab section
3576 can be optionally omitted, provided that .exidx does not
3577 refer to it. If the .exidx is erroneous and does refer to
3578 .extab even though .extab is missing, the range checks done
3579 by GET_EX_U32 in ExtabEntryExtract in readexidx.c should
3580 prevent any invalid memory accesses, and cause the .extab to
3581 be rejected as invalid.
3583 FIXME:
3584 * check with m_aspacemgr that the entire [exidx_avma, +exidx_size)
3585 and [extab_avma, +extab_size) areas are readable, since we're
3586 reading this stuff out of the running image (not from a file/socket)
3587 and we don't want to segfault.
3588 * DebugInfo::exidx_bias and use text_bias instead.
3589 I think it's always the same.
3590 * remove DebugInfo::{extab_bias, exidx_svma, extab_svma} since
3591 they are never used.
3593 if (di->exidx_present
3594 && di->cfsi_used == 0
3595 && di->text_present && di->text_size > 0) {
3596 Addr text_last_svma = di->text_svma + di->text_size - 1;
3597 ML_(read_exidx)( di, (UChar*)di->exidx_avma, di->exidx_size,
3598 (UChar*)di->extab_avma, di->extab_size,
3599 text_last_svma,
3600 di->exidx_bias );
3602 # endif /* defined(VGA_arm) */
3604 } /* "Find interesting sections, read the symbol table(s), read any debug
3605 information" (a local scope) */
3607 /* TOPLEVEL */
3608 res = True;
3610 /* If reading Dwarf3 variable type/location info, print a line
3611 showing the number of variables read for each object.
3612 (Currently disabled -- is a sanity-check mechanism for
3613 exp-sgcheck.) */
3614 if (0 && VG_(clo_read_var_info)) {
3615 UWord nVars = 0;
3616 if (di->varinfo) {
3617 for (j = 0; j < VG_(sizeXA)(di->varinfo); j++) {
3618 OSet* /* of DiAddrRange */ scope
3619 = *(OSet**)VG_(indexXA)(di->varinfo, j);
3620 vg_assert(scope);
3621 VG_(OSetGen_ResetIter)( scope );
3622 while (True) {
3623 DiAddrRange* range = VG_(OSetGen_Next)( scope );
3624 if (!range) break;
3625 vg_assert(range->vars);
3626 Word w = VG_(sizeXA)(range->vars);
3627 vg_assert(w >= 0);
3628 if (0) VG_(printf)("range %#lx %#lx %ld\n",
3629 range->aMin, range->aMax, w);
3630 nVars += (UWord)w;
3634 VG_(umsg)("VARINFO: %7lu vars %7lu text_size %s\n",
3635 nVars, di->text_size, di->fsm.filename);
3637 /* TOPLEVEL */
3639 out:
3641 /* Last, but not least, detach from the image(s). */
3642 if (mimg) ML_(img_done)(mimg);
3643 if (dimg) ML_(img_done)(dimg);
3644 if (aimg) ML_(img_done)(aimg);
3646 if (svma_ranges) VG_(deleteXA)(svma_ranges);
3648 return res;
3649 } /* out: */
3651 /* NOTREACHED */
3654 Bool ML_(check_elf_and_get_rw_loads) ( Int fd, const HChar* filename, Int * rw_load_count )
3656 Bool res, ok;
3657 UWord i;
3658 DiImage* mimg = NULL;
3659 DiOffT ehdr_mioff = 0;
3660 DiOffT phdr_mioff = 0;
3661 UWord phdr_mnent = 0U;
3662 UWord phdr_ment_szB = 0U;
3664 res = False;
3666 mimg = ML_(img_from_fd)(fd, filename);
3667 if (mimg == NULL) {
3668 VG_(message)(Vg_UserMsg, "warning: connection to image %s failed\n",
3669 filename );
3670 VG_(message)(Vg_UserMsg, " cannot read program headers \n" );
3671 return False;
3674 ok = is_elf_object_file_by_DiImage(mimg, False);
3675 if (!ok) {
3676 goto out;
3679 ElfXX_Ehdr ehdr_m;
3680 Elf64_Word flag_x;
3681 #if defined(VGA_amd64) || defined(VGA_ppc64be) || defined(VGA_ppc64le) || defined(VGA_arm) || defined(VGA_arm64)
3682 flag_x = PF_X;
3683 #else
3684 flag_x = 0;
3685 #endif
3687 #if defined(VGO_solaris)
3688 flag_x = 0;
3689 #endif
3691 vg_assert(ehdr_mioff == 0); // ensured by its initialisation
3692 ok = ML_(img_valid)(mimg, ehdr_mioff, sizeof(ehdr_m));
3693 vg_assert(ok); // ML_(is_elf_object_file) should ensure this
3694 ML_(img_get)(&ehdr_m, mimg, ehdr_mioff, sizeof(ehdr_m));
3696 phdr_mioff = ehdr_mioff + ehdr_m.e_phoff;
3697 phdr_mnent = ehdr_m.e_phnum;
3698 phdr_ment_szB = ehdr_m.e_phentsize;
3700 for (i = 0U; i < phdr_mnent; i++) {
3701 ElfXX_Phdr a_phdr;
3702 ML_(img_get)(&a_phdr, mimg,
3703 INDEX_BIS(phdr_mioff, i, phdr_ment_szB),
3704 sizeof(a_phdr));
3706 if (a_phdr.p_type == PT_LOAD) {
3707 if (a_phdr.p_memsz > 0) {
3708 if (((a_phdr.p_flags & (PF_R | PF_W)) == (PF_R | PF_W)) &&
3709 ((a_phdr.p_flags & flag_x) == 0)) {
3710 ++*rw_load_count;
3714 * Hold your horses
3715 * Just because The ELF file contains 2 RW PT_LOAD segments it
3716 * doesn't mean that Valgrind will also make 2 calls to
3717 * VG_(di_notify_mmap). If the stars are all aligned
3718 * (which usually means that the ELF file is the client
3719 * executable with the segment offset for the
3720 * second PT_LOAD falls exactly on 0x1000) then the NSegements
3721 * will get merged and VG_(di_notify_mmap) only gets called once. */
3722 if (*rw_load_count == 2 &&
3723 ehdr_m.e_type == ET_EXEC &&
3724 a_phdr.p_offset == VG_PGROUNDDN(a_phdr.p_offset) )
3726 *rw_load_count = 1;
3730 } /* for (i = 0; i < phdr_Mnent; i++) ... */
3732 res = True;
3734 out:
3736 /* Last, but not least, detach from the image(s). */
3737 if (mimg) ML_(img_free)(mimg);
3739 return res;
3740 } /* out: */
3742 /* NOTREACHED */
3747 #endif // defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
3749 /*--------------------------------------------------------------------*/
3750 /*--- end ---*/
3751 /*--------------------------------------------------------------------*/