Skip updating rodata avma and tracing when there are non-contiguous rodata sections.
[valgrind.git] / coregrind / m_debuginfo / readelf.c
blob16b5340a53ed365fd6efc2524f55ea734c4ecab9
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_debuglog.h"
36 #include "pub_core_debuginfo.h"
37 #include "pub_core_libcbase.h"
38 #include "pub_core_libcprint.h"
39 #include "pub_core_libcassert.h"
40 #include "pub_core_libcfile.h"
41 #include "pub_core_libcproc.h"
42 #include "pub_core_machine.h" /* VG_ELF_CLASS */
43 #include "pub_core_options.h"
44 #include "pub_core_oset.h"
45 #include "pub_core_pathscan.h" /* find_executable */
46 #include "pub_core_syscall.h"
47 #include "pub_core_tooliface.h" /* VG_(needs) */
48 #include "pub_core_xarray.h"
49 #include "pub_core_libcproc.h"
50 #include "priv_misc.h" /* dinfo_zalloc/free/strdup */
51 #include "priv_image.h"
52 #include "priv_d3basics.h"
53 #include "priv_tytypes.h"
54 #include "priv_storage.h"
55 #include "priv_readelf.h" /* self */
56 #include "priv_readdwarf.h" /* 'cos ELF contains DWARF */
57 #include "priv_readdwarf3.h"
58 #include "priv_readexidx.h"
59 #include "config.h"
61 /* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
62 #include <elf.h>
63 #if defined(VGO_solaris)
64 #include <sys/link.h> /* ElfXX_Dyn, DT_* */
65 #endif
66 /* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
68 #if !defined(HAVE_ELF32_CHDR)
69 typedef struct {
70 Elf32_Word ch_type;
71 Elf32_Word ch_size;
72 Elf32_Word ch_addralign;
73 } Elf32_Chdr;
74 #endif
76 #if !defined(HAVE_ELF64_CHDR)
77 typedef struct {
78 Elf64_Word ch_type;
79 Elf64_Word ch_reserved;
80 Elf64_Xword ch_size;
81 Elf64_Xword ch_addralign;
82 } Elf64_Chdr;
83 #endif
85 #if !defined(SHF_COMPRESSED)
86 #define SHF_COMPRESSED (1 << 11)
87 #endif
89 #if !defined(ELFCOMPRESS_ZLIB)
90 #define ELFCOMPRESS_ZLIB 1
91 #endif
93 #define SIZE_OF_ZLIB_HEADER 12
95 /*------------------------------------------------------------*/
96 /*--- 32/64-bit parameterisation ---*/
97 /*------------------------------------------------------------*/
99 /* For all the ELF macros and types which specify '32' or '64',
100 select the correct variant for this platform and give it
101 an 'XX' name. Then use the 'XX' variant consistently in
102 the rest of this file.
104 #if VG_WORDSIZE == 4
105 # define ElfXX_Ehdr Elf32_Ehdr
106 # define ElfXX_Shdr Elf32_Shdr
107 # define ElfXX_Phdr Elf32_Phdr
108 # define ElfXX_Nhdr Elf32_Nhdr
109 # define ElfXX_Sym Elf32_Sym
110 # define ElfXX_Off Elf32_Off
111 # define ElfXX_Word Elf32_Word
112 # define ElfXX_Addr Elf32_Addr
113 # define ElfXX_Dyn Elf32_Dyn
114 # define ELFXX_ST_BIND ELF32_ST_BIND
115 # define ELFXX_ST_TYPE ELF32_ST_TYPE
116 # define ElfXX_Chdr Elf32_Chdr
118 #elif VG_WORDSIZE == 8
119 # define ElfXX_Ehdr Elf64_Ehdr
120 # define ElfXX_Shdr Elf64_Shdr
121 # define ElfXX_Phdr Elf64_Phdr
122 # define ElfXX_Nhdr Elf64_Nhdr
123 # define ElfXX_Sym Elf64_Sym
124 # define ElfXX_Off Elf64_Off
125 # define ElfXX_Word Elf64_Word
126 # define ElfXX_Addr Elf64_Addr
127 # define ElfXX_Dyn Elf64_Dyn
128 # define ELFXX_ST_BIND ELF64_ST_BIND
129 # define ELFXX_ST_TYPE ELF64_ST_TYPE
130 # define ElfXX_Chdr Elf64_Chdr
132 #else
133 # error "VG_WORDSIZE should be 4 or 8"
134 #endif
137 /*------------------------------------------------------------*/
138 /*--- ---*/
139 /*--- Read symbol table and line info from ELF files. ---*/
140 /*--- ---*/
141 /*------------------------------------------------------------*/
143 /* readelf.c parses ELF files and acquires symbol table info from
144 them. It calls onwards to readdwarf.c to read DWARF2/3 line number
145 and call frame info found. */
147 /* Identify an ELF object file by peering at the first few bytes of
148 it. */
150 Bool ML_(is_elf_object_file)( const void* image, SizeT n_image, Bool rel_ok )
152 const ElfXX_Ehdr* ehdr = image;
153 Int ok = 1;
155 if (n_image < sizeof(ElfXX_Ehdr))
156 return False;
158 ok &= (ehdr->e_ident[EI_MAG0] == 0x7F
159 && ehdr->e_ident[EI_MAG1] == 'E'
160 && ehdr->e_ident[EI_MAG2] == 'L'
161 && ehdr->e_ident[EI_MAG3] == 'F');
162 ok &= (ehdr->e_ident[EI_CLASS] == VG_ELF_CLASS
163 && ehdr->e_ident[EI_DATA] == VG_ELF_DATA2XXX
164 && ehdr->e_ident[EI_VERSION] == EV_CURRENT);
165 ok &= (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN
166 || (rel_ok && ehdr->e_type == ET_REL));
167 ok &= (ehdr->e_machine == VG_ELF_MACHINE);
168 ok &= (ehdr->e_version == EV_CURRENT);
169 ok &= (ehdr->e_shstrndx != SHN_UNDEF);
170 ok &= (ehdr->e_shoff != 0 && ehdr->e_shnum != 0);
171 ok &= ((ehdr->e_phoff != 0 && ehdr->e_phnum != 0)
172 || ehdr->e_type == ET_REL);
174 return ok ? True : False;
178 /* The same thing, but operating on a DiImage instead. */
180 static Bool is_elf_object_file_by_DiImage( DiImage* img, Bool rel_ok )
182 /* Be sure this doesn't make the frame too big. */
183 vg_assert(sizeof(ElfXX_Ehdr) <= 512);
185 ElfXX_Ehdr ehdr;
186 if (!ML_(img_valid)(img, 0, sizeof(ehdr)))
187 return False;
189 ML_(img_get)(&ehdr, img, 0, sizeof(ehdr));
190 return ML_(is_elf_object_file)( &ehdr, sizeof(ehdr), rel_ok );
194 /* Show a raw ELF symbol, given its in-image address and name. */
196 static
197 void show_raw_elf_symbol ( DiImage* strtab_img,
198 Int i,
199 const ElfXX_Sym* sym,
200 DiOffT sym_name_ioff, Addr sym_svma,
201 Bool ppc64_linux_format )
203 const HChar* space = ppc64_linux_format ? " " : "";
204 VG_(printf)("raw symbol [%4d]: ", i);
205 switch (ELFXX_ST_BIND(sym->st_info)) {
206 case STB_LOCAL: VG_(printf)("LOC "); break;
207 case STB_GLOBAL: VG_(printf)("GLO "); break;
208 case STB_WEAK: VG_(printf)("WEA "); break;
209 case STB_LOPROC: VG_(printf)("lop "); break;
210 case STB_HIPROC: VG_(printf)("hip "); break;
211 default: VG_(printf)("??? "); break;
213 switch (ELFXX_ST_TYPE(sym->st_info)) {
214 case STT_NOTYPE: VG_(printf)("NOT "); break;
215 case STT_OBJECT: VG_(printf)("OBJ "); break;
216 case STT_FUNC: VG_(printf)("FUN "); break;
217 case STT_SECTION: VG_(printf)("SEC "); break;
218 case STT_FILE: VG_(printf)("FIL "); break;
219 case STT_LOPROC: VG_(printf)("lop "); break;
220 case STT_HIPROC: VG_(printf)("hip "); break;
221 default: VG_(printf)("??? "); break;
223 HChar* sym_name = NULL;
224 if (sym->st_name)
225 sym_name = ML_(img_strdup)(strtab_img, "di.sres.1", sym_name_ioff);
226 VG_(printf)(": svma %#010lx, %ssz %4llu %s\n",
227 sym_svma, space, (ULong)(sym->st_size + 0UL),
228 (sym_name ? sym_name : "NONAME") );
229 if (sym_name)
230 ML_(dinfo_free)(sym_name);
234 /* Decide whether SYM is something we should collect, and if so, copy
235 relevant info to the _OUT arguments. For {x86,amd64,ppc32}-linux
236 this is straightforward - the name, address, size are copied out
237 unchanged.
239 There is a bit of a kludge re data symbols (see KLUDGED BSS CHECK
240 below): we assume that the .bss is mapped immediately after .data,
241 and so accept any data symbol which exists in the range [start of
242 .data, size of .data + size of .bss). I don't know if this is
243 really correct/justifiable, or not.
245 For ppc64be-linux it's more complex. If the symbol is seen to be in
246 the .opd section, it is taken to be a function descriptor, and so
247 a dereference is attempted, in order to get hold of the real entry
248 point address. Also as part of the dereference, there is an attempt
249 to calculate the TOC pointer (R2 value) associated with the symbol.
251 To support the ppc64be-linux pre-"dotless" ABI (prior to gcc 4.0.0),
252 if the symbol is seen to be outside the .opd section and its name
253 starts with a dot, an .opd deference is not attempted, and no TOC
254 pointer is calculated, but the leading dot is removed from the
255 name.
257 As a result, on ppc64be-linux, the caller of this function may have
258 to piece together the real size, address, name of the symbol from
259 multiple calls to this function. Ugly and confusing.
261 static
262 Bool get_elf_symbol_info (
263 /* INPUTS */
264 struct _DebugInfo* di, /* containing DebugInfo */
265 const ElfXX_Sym* sym, /* ELF symbol */
266 DiOffT sym_name_ioff, /* name, may be absent (DiOffT_INVALID) */
267 const DiSlice* escn_strtab, /* holds the name */
268 Addr sym_svma, /* address as stated in the object file */
269 Bool symtab_in_debug, /* symbol table is in the debug file */
270 const DiSlice* escn_opd, /* the .opd (ppc64be-linux only) */
271 PtrdiffT opd_bias, /* for biasing AVMAs found in .opd */
272 /* OUTPUTS */
273 DiOffT* sym_name_out_ioff, /* name (in strtab) we should record */
274 SymAVMAs* sym_avmas_out, /* sym avmas we should record */
275 Int* sym_size_out, /* symbol size */
276 Bool* from_opd_out, /* ppc64be-linux only: did we deref an
277 .opd entry? */
278 Bool* is_text_out, /* is this a text symbol? */
279 Bool* is_ifunc_out, /* is this a STT_GNU_IFUNC function ?*/
280 Bool* is_global_out /* is this a global symbol ?*/
283 Bool plausible;
284 # if defined(VGP_ppc64be_linux)
285 Bool is_in_opd;
286 # endif
287 Bool in_text, in_data, in_sdata, in_rodata, in_bss, in_sbss;
288 Addr text_svma, data_svma, sdata_svma, rodata_svma, bss_svma, sbss_svma;
289 PtrdiffT text_bias, data_bias, sdata_bias, rodata_bias, bss_bias, sbss_bias;
290 # if defined(VGPV_arm_linux_android) \
291 || defined(VGPV_x86_linux_android) \
292 || defined(VGPV_mips32_linux_android) \
293 || defined(VGPV_arm64_linux_android)
294 Addr available_size = 0;
295 #define COMPUTE_AVAILABLE_SIZE(segsvma, segsize) \
296 available_size = segsvma + segsize - sym_svma
297 #else
298 #define COMPUTE_AVAILABLE_SIZE(segsvma, segsize)
299 #endif
301 /* Set defaults */
302 *sym_name_out_ioff = sym_name_ioff;
303 (*sym_avmas_out).main = sym_svma; /* we will bias this shortly */
304 *is_text_out = True;
305 SET_TOCPTR_AVMA(*sym_avmas_out, 0); /* default to unknown/inapplicable */
306 SET_LOCAL_EP_AVMA(*sym_avmas_out, 0); /* default to unknown/inapplicable */
307 *from_opd_out = False;
308 *is_ifunc_out = False;
309 *is_global_out = False;
311 /* Get the symbol size, but restrict it to fit in a signed 32 bit
312 int. Also, deal with the stupid case of negative size by making
313 the size be 1. Note that sym->st_size has type UWord,
314 effectively. */
315 { Word size_tmp = (Word)sym->st_size;
316 Word max_Int = (1LL << 31) - 1;
317 if (size_tmp < 0) size_tmp = 1;
318 if (size_tmp > max_Int) size_tmp = max_Int;
319 *sym_size_out = (Int)size_tmp;
321 /* After this point refer only to *sym_size_out and not to
322 sym->st_size. */
324 /* Figure out if we're interested in the symbol. Firstly, is it of
325 the right flavour? */
326 plausible
327 = (ELFXX_ST_BIND(sym->st_info) == STB_GLOBAL
328 || ELFXX_ST_BIND(sym->st_info) == STB_LOCAL
329 || ELFXX_ST_BIND(sym->st_info) == STB_WEAK
332 (ELFXX_ST_TYPE(sym->st_info) == STT_FUNC
333 || ELFXX_ST_TYPE(sym->st_info) == STT_OBJECT
334 # ifdef STT_GNU_IFUNC
335 || ELFXX_ST_TYPE(sym->st_info) == STT_GNU_IFUNC
336 # endif
339 /* Work out the svma and bias for each section as it will appear in
340 addresses in the symbol table. */
341 if (symtab_in_debug) {
342 text_svma = di->text_debug_svma;
343 text_bias = di->text_debug_bias;
344 data_svma = di->data_debug_svma;
345 data_bias = di->data_debug_bias;
346 sdata_svma = di->sdata_debug_svma;
347 sdata_bias = di->sdata_debug_bias;
348 rodata_svma = di->rodata_debug_svma;
349 rodata_bias = di->rodata_debug_bias;
350 bss_svma = di->bss_debug_svma;
351 bss_bias = di->bss_debug_bias;
352 sbss_svma = di->sbss_debug_svma;
353 sbss_bias = di->sbss_debug_bias;
354 } else {
355 text_svma = di->text_svma;
356 text_bias = di->text_bias;
357 data_svma = di->data_svma;
358 data_bias = di->data_bias;
359 sdata_svma = di->sdata_svma;
360 sdata_bias = di->sdata_bias;
361 rodata_svma = di->rodata_svma;
362 rodata_bias = di->rodata_bias;
363 bss_svma = di->bss_svma;
364 bss_bias = di->bss_bias;
365 sbss_svma = di->sbss_svma;
366 sbss_bias = di->sbss_bias;
369 /* Now bias (*sym_avmas_out).main accordingly by figuring out exactly which
370 section the symbol is from and bias accordingly. Screws up if
371 the previously deduced section svma address ranges are wrong. */
372 if (di->text_present
373 && di->text_size > 0
374 && sym_svma >= text_svma
375 && sym_svma < text_svma + di->text_size) {
376 *is_text_out = True;
377 (*sym_avmas_out).main += text_bias;
378 COMPUTE_AVAILABLE_SIZE(text_svma, di->text_size);
379 } else
380 if (di->data_present
381 && di->data_size > 0
382 && sym_svma >= data_svma
383 && sym_svma < data_svma + di->data_size) {
384 *is_text_out = False;
385 (*sym_avmas_out).main += data_bias;
386 COMPUTE_AVAILABLE_SIZE(data_svma, di->data_size);
387 } else
388 if (di->sdata_present
389 && di->sdata_size > 0
390 && sym_svma >= sdata_svma
391 && sym_svma < sdata_svma + di->sdata_size) {
392 *is_text_out = False;
393 (*sym_avmas_out).main += sdata_bias;
394 COMPUTE_AVAILABLE_SIZE(sdata_svma, di->sdata_size);
395 } else
396 if (di->rodata_present
397 && di->rodata_size > 0
398 && sym_svma >= rodata_svma
399 && sym_svma < rodata_svma + di->rodata_size) {
400 *is_text_out = False;
401 (*sym_avmas_out).main += rodata_bias;
402 COMPUTE_AVAILABLE_SIZE(rodata_svma, di->rodata_size);
403 } else
404 if (di->bss_present
405 && di->bss_size > 0
406 && sym_svma >= bss_svma
407 && sym_svma < bss_svma + di->bss_size) {
408 *is_text_out = False;
409 (*sym_avmas_out).main += bss_bias;
410 COMPUTE_AVAILABLE_SIZE(bss_svma, di->bss_size);
411 } else
412 if (di->sbss_present
413 && di->sbss_size > 0
414 && sym_svma >= sbss_svma
415 && sym_svma < sbss_svma + di->sbss_size) {
416 *is_text_out = False;
417 (*sym_avmas_out).main += sbss_bias;
418 COMPUTE_AVAILABLE_SIZE(sbss_svma, di->sbss_size);
419 } else {
420 /* Assume it's in .text. Is this a good idea? */
421 *is_text_out = True;
422 (*sym_avmas_out).main += text_bias;
425 # ifdef STT_GNU_IFUNC
426 /* Check for indirect functions. */
427 if (*is_text_out
428 && ELFXX_ST_TYPE(sym->st_info) == STT_GNU_IFUNC) {
429 *is_ifunc_out = True;
431 # endif
433 if (ELFXX_ST_BIND(sym->st_info) == STB_GLOBAL
434 || ELFXX_ST_BIND(sym->st_info) == STB_WEAK) {
435 *is_global_out = True;
438 # if defined(VGP_ppc64be_linux)
439 /* Allow STT_NOTYPE in the very special case where we're running on
440 ppc64be-linux and the symbol is one which the .opd-chasing hack
441 below will chase. */
442 if (!plausible
443 && *is_text_out
444 && ELFXX_ST_TYPE(sym->st_info) == STT_NOTYPE
445 && *sym_size_out > 0
446 && di->opd_present
447 && di->opd_size > 0
448 && (*sym_avmas_out).main >= di->opd_avma
449 && (*sym_avmas_out).main < di->opd_avma + di->opd_size)
450 plausible = True;
451 # endif
453 if (!plausible)
454 return False;
456 /* Ignore if nameless. */
457 if (sym_name_ioff == DiOffT_INVALID
458 || /* VG_(strlen)(sym_name) == 0 */
459 /* equivalent but cheaper ... */
460 ML_(img_get_UChar)(escn_strtab->img, sym_name_ioff) == '\0') {
461 if (TRACE_SYMTAB_ENABLED) {
462 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
463 "di.gesi.1", sym_name_ioff);
464 TRACE_SYMTAB(" ignore -- nameless: %s\n", sym_name);
465 if (sym_name) ML_(dinfo_free)(sym_name);
467 return False;
470 /* Ignore if zero-sized. Except on Android:
472 On Android 2.3.5, some of the symbols that Memcheck needs to
473 intercept (for noise reduction purposes) have zero size, due to
474 lack of .size directives in handwritten assembly sources. So we
475 can't reject them out of hand -- instead give them a bogusly
476 large size and let canonicaliseSymtab trim them so they don't
477 overlap any following symbols. At least the following symbols
478 are known to be affected:
480 in /system/lib/libc.so: strlen strcmp strcpy memcmp memcpy
481 in /system/bin/linker: __dl_strcmp __dl_strlen
483 if (*sym_size_out == 0) {
484 # if defined(VGPV_arm_linux_android) \
485 || defined(VGPV_x86_linux_android) \
486 || defined(VGPV_mips32_linux_android) \
487 || defined(VGPV_arm64_linux_android)
488 *sym_size_out = available_size ? available_size : 2048;
489 # else
490 if (TRACE_SYMTAB_ENABLED) {
491 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
492 "di.gesi.2", sym_name_ioff);
493 TRACE_SYMTAB(" ignore -- size=0: %s\n", sym_name);
494 if (sym_name) ML_(dinfo_free)(sym_name);
496 return False;
497 # endif
500 /* This seems to significantly reduce the number of junk
501 symbols, and particularly reduces the number of
502 overlapping address ranges. Don't ask me why ... */
503 if ((Int)sym->st_value == 0) {
504 if (TRACE_SYMTAB_ENABLED) {
505 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
506 "di.gesi.3", sym_name_ioff);
507 TRACE_SYMTAB( " ignore -- valu=0: %s\n", sym_name);
508 if (sym_name) ML_(dinfo_free)(sym_name);
510 return False;
513 /* If it's apparently in a GOT or PLT, it's really a reference to a
514 symbol defined elsewhere, so ignore it. */
515 if (di->got_present
516 && di->got_size > 0
517 && (*sym_avmas_out).main >= di->got_avma
518 && (*sym_avmas_out).main < di->got_avma + di->got_size) {
519 if (TRACE_SYMTAB_ENABLED) {
520 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
521 "di.gesi.4", sym_name_ioff);
522 TRACE_SYMTAB(" ignore -- in GOT: %s\n", sym_name);
523 if (sym_name) ML_(dinfo_free)(sym_name);
525 return False;
527 if (di->plt_present
528 && di->plt_size > 0
529 && (*sym_avmas_out).main >= di->plt_avma
530 && (*sym_avmas_out).main < di->plt_avma + di->plt_size) {
531 if (TRACE_SYMTAB_ENABLED) {
532 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
533 "di.gesi.5", sym_name_ioff);
534 TRACE_SYMTAB(" ignore -- in PLT: %s\n", sym_name);
535 if (sym_name) ML_(dinfo_free)(sym_name);
537 return False;
540 /* ppc64be-linux nasty hack: if the symbol is in an .opd section,
541 then really what we have is the address of a function
542 descriptor. So use the first word of that as the function's
543 text.
545 See thread starting at
546 http://gcc.gnu.org/ml/gcc-patches/2004-08/msg00557.html
548 # if defined(VGP_ppc64be_linux)
549 /* Host and guest may have different Endianness, used by BE only */
550 is_in_opd = False;
551 # endif
553 if (di->opd_present
554 && di->opd_size > 0
555 && (*sym_avmas_out).main >= di->opd_avma
556 && (*sym_avmas_out).main < di->opd_avma + di->opd_size) {
557 # if !defined(VGP_ppc64be_linux)
558 if (TRACE_SYMTAB_ENABLED) {
559 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
560 "di.gesi.6", sym_name_ioff);
561 TRACE_SYMTAB(" ignore -- in OPD: %s\n", sym_name);
562 if (sym_name) ML_(dinfo_free)(sym_name);
564 return False;
565 # else
566 Int offset_in_opd;
567 Bool details = 1||False;
569 if (details)
570 TRACE_SYMTAB("opdXXX: opd_bias %p, sym_svma_out %p\n",
571 (void*)(opd_bias), (void*)(*sym_avmas_out).main);
573 if (!VG_IS_8_ALIGNED((*sym_avmas_out).main)) {
574 if (TRACE_SYMTAB_ENABLED) {
575 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
576 "di.gesi.6a", sym_name_ioff);
577 TRACE_SYMTAB(" ignore -- not 8-aligned: %s\n", sym_name);
578 if (sym_name) ML_(dinfo_free)(sym_name);
580 return False;
583 /* (*sym_avmas_out).main is a avma pointing into the .opd section. We
584 know the vma of the opd section start, so we can figure out
585 how far into the opd section this is. */
587 offset_in_opd = (Addr)(*sym_avmas_out).main - (Addr)(di->opd_avma);
588 if (offset_in_opd < 0 || offset_in_opd >= di->opd_size) {
589 if (TRACE_SYMTAB_ENABLED) {
590 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
591 "di.gesi.6a", sym_name_ioff);
592 TRACE_SYMTAB(" ignore -- invalid OPD offset: %s\n", sym_name);
593 if (sym_name) ML_(dinfo_free)(sym_name);
595 return False;
598 /* Now we want to know what's at that offset in the .opd
599 section. We can't look in the running image since it won't
600 necessarily have been mapped. But we can consult the oimage.
601 opd_img is the start address of the .opd in the oimage.
602 Hence: */
604 ULong fn_descr[2]; /* is actually 3 words, but we need only 2 */
605 if (!ML_(img_valid)(escn_opd->img, escn_opd->ioff + offset_in_opd,
606 sizeof(fn_descr))) {
607 if (TRACE_SYMTAB_ENABLED) {
608 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
609 "di.gesi.6b", sym_name_ioff);
610 TRACE_SYMTAB(" ignore -- invalid OPD fn_descr offset: %s\n",
611 sym_name);
612 if (sym_name) ML_(dinfo_free)(sym_name);
615 return False;
618 /* This can't fail now, because we just checked the offset
619 above. */
620 ML_(img_get)(&fn_descr[0], escn_opd->img,
621 escn_opd->ioff + offset_in_opd, sizeof(fn_descr));
623 if (details)
624 TRACE_SYMTAB("opdXXY: offset %d, fn_descr %p\n",
625 offset_in_opd, fn_descr);
626 if (details)
627 TRACE_SYMTAB("opdXXZ: *fn_descr %p\n", (void*)(fn_descr[0]));
629 /* opd_bias is the what we have to add to SVMAs found in .opd to
630 get plausible .text AVMAs for the entry point, and .data
631 AVMAs (presumably) for the TOC locations. We use the caller
632 supplied value (which is di->text_bias) for both of these.
633 Not sure why that is correct - it seems to work, and sounds
634 OK for fn_descr[0], but surely we need to use the data bias
635 and not the text bias for fn_descr[1] ? Oh Well.
637 (*sym_avmas_out).main = fn_descr[0] + opd_bias;
638 SET_TOCPTR_AVMA(*sym_avmas_out, fn_descr[1] + opd_bias);
639 *from_opd_out = True;
640 is_in_opd = True;
642 /* Do a final sanity check: if the symbol falls outside the
643 DebugInfo's mapped range, ignore it. Since (*sym_avmas_out).main has
644 been updated, that can be achieved simply by falling through
645 to the test below. */
647 # endif /* ppc64-linux nasty hack */
650 /* Here's yet another ppc64-linux hack. Get rid of leading dot if
651 the symbol is outside .opd. */
652 # if defined(VGP_ppc64be_linux)
653 if (di->opd_size > 0
654 && !is_in_opd
655 && *sym_name_out_ioff != DiOffT_INVALID
656 && ML_(img_get_UChar)(escn_strtab->img, *sym_name_out_ioff) == '.') {
657 vg_assert(!(*from_opd_out));
658 (*sym_name_out_ioff)++;
660 # endif
662 /* If no part of the symbol falls within the mapped range,
663 ignore it. */
665 in_text
666 = di->text_present
667 && di->text_size > 0
668 && !((*sym_avmas_out).main + *sym_size_out <= di->text_avma
669 || (*sym_avmas_out).main >= di->text_avma + di->text_size);
671 in_data
672 = di->data_present
673 && di->data_size > 0
674 && !((*sym_avmas_out).main + *sym_size_out <= di->data_avma
675 || (*sym_avmas_out).main >= di->data_avma + di->data_size);
677 in_sdata
678 = di->sdata_present
679 && di->sdata_size > 0
680 && !((*sym_avmas_out).main + *sym_size_out <= di->sdata_avma
681 || (*sym_avmas_out).main >= di->sdata_avma + di->sdata_size);
683 in_rodata
684 = di->rodata_present
685 && di->rodata_size > 0
686 && !((*sym_avmas_out).main + *sym_size_out <= di->rodata_avma
687 || (*sym_avmas_out).main >= di->rodata_avma + di->rodata_size);
689 in_bss
690 = di->bss_present
691 && di->bss_size > 0
692 && !((*sym_avmas_out).main + *sym_size_out <= di->bss_avma
693 || (*sym_avmas_out).main >= di->bss_avma + di->bss_size);
695 in_sbss
696 = di->sbss_present
697 && di->sbss_size > 0
698 && !((*sym_avmas_out).main + *sym_size_out <= di->sbss_avma
699 || (*sym_avmas_out).main >= di->sbss_avma + di->sbss_size);
702 if (*is_text_out) {
703 /* This used to reject any symbol falling outside the text
704 segment ("if (!in_text) ..."). Now it is relaxed slightly,
705 to reject only symbols which fall outside the area mapped
706 r-x. This is in accordance with r7427. See
707 "Comment_Regarding_Text_Range_Checks" in storage.c for
708 background. */
709 Bool in_rx;
710 vg_assert(di->fsm.have_rx_map);
711 /* This could actually wrap around and cause
712 ML_(find_rx_mapping) to assert. But that seems so unlikely,
713 let's wait for it to happen before fixing it. */
714 in_rx = (ML_(find_rx_mapping)(
716 (*sym_avmas_out).main,
717 (*sym_avmas_out).main + *sym_size_out - 1) != NULL);
718 if (in_text)
719 vg_assert(in_rx);
720 if (!in_rx) {
721 TRACE_SYMTAB(
722 "ignore -- %#lx .. %#lx outside .text svma range %#lx .. %#lx\n",
723 (*sym_avmas_out).main, (*sym_avmas_out).main + *sym_size_out - 1,
724 di->text_avma,
725 di->text_avma + di->text_size - 1);
726 return False;
728 } else {
729 if (!(in_data || in_sdata || in_rodata || in_bss || in_sbss)) {
730 TRACE_SYMTAB(
731 "ignore -- %#lx .. %#lx outside .data / .sdata / .rodata "
732 "/ .bss / .sbss svma ranges\n",
733 (*sym_avmas_out).main, (*sym_avmas_out).main + *sym_size_out - 1);
734 return False;
738 # if defined(VGP_ppc64be_linux)
739 if (di->opd_present && di->opd_size > 0) {
740 vg_assert((*sym_avmas_out).main + *sym_size_out <= di->opd_avma
741 || (*sym_avmas_out).main >= di->opd_avma + di->opd_size);
743 #endif
745 # if defined(VGP_ppc64le_linux)
746 /* PPC64 LE ABI uses three bits in the st_other field to indicate the number
747 * of instructions between the function's global and local entry points. An
748 * offset of 0 indicates that there is one entry point. The value must be:
750 * 0 - one entry point, local and global are the same
751 * 1 - reserved
752 * 2 - local entry point is one instruction after the global entry point
753 * 3 - local entry point is two instructions after the global entry point
754 * 4 - local entry point is four instructions after the global entry point
755 * 5 - local entry point is eight instructions after the global entry point
756 * 6 - local entry point is sixteen instructions after the global entry point
757 * 7 - reserved
759 * Extract the three bit field from the other field is done by:
760 * (other_field & STO_PPC64_LOCAL_MASK) >> STO_PPC_LOCAL_BIT
762 * where the #define values are given in include/elf/powerpc.h file for
763 * the PPC binutils.
765 * conversion of the three bit field to bytes is given by
767 * ((1 << bit_field) >> 2) << 2
770 #define STO_PPC64_LOCAL_BIT 5
771 #define STO_PPC64_LOCAL_MASK (7 << STO_PPC64_LOCAL_BIT)
773 unsigned int bit_field, dist_to_local_entry;
774 /* extract the other filed */
775 bit_field = (sym->st_other & STO_PPC64_LOCAL_MASK) >> STO_PPC64_LOCAL_BIT;
777 if ((bit_field > 0) && (bit_field < 7)) {
778 /* store the local entry point address */
779 dist_to_local_entry = ((1 << bit_field) >> 2) << 2;
780 SET_LOCAL_EP_AVMA(*sym_avmas_out,
781 (*sym_avmas_out).main + dist_to_local_entry);
783 if (TRACE_SYMTAB_ENABLED) {
784 HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
785 "di.gesi.5", sym_name_ioff);
786 VG_(printf)("Local entry point: %s at %#010x\n",
787 sym_name,
788 (unsigned int)GET_LOCAL_EP_AVMA(*sym_avmas_out));
792 # endif
794 /* Acquire! */
795 return True;
799 /* Read an ELF symbol table (normal or dynamic). This one is for the
800 "normal" case ({x86,amd64,ppc32,arm,mips32,mips64, ppc64le}-linux). */
801 static
802 __attribute__((unused)) /* not referred to on all targets */
803 void read_elf_symtab__normal(
804 struct _DebugInfo* di, const HChar* tab_name,
805 DiSlice* escn_symtab,
806 DiSlice* escn_strtab,
807 DiSlice* escn_opd, /* ppc64be-linux only */
808 Bool symtab_in_debug
811 if (escn_strtab->img == NULL || escn_symtab->img == NULL) {
812 HChar buf[VG_(strlen)(tab_name) + 40];
813 VG_(sprintf)(buf, " object doesn't have a %s", tab_name);
814 ML_(symerr)(di, False, buf);
815 return;
818 TRACE_SYMTAB("\n--- Reading (ELF, standard) %s (%llu entries) ---\n",
819 tab_name, escn_symtab->szB/sizeof(ElfXX_Sym) );
821 /* Perhaps should start at i = 1; ELF docs suggest that entry
822 0 always denotes 'unknown symbol'. */
823 Word i;
824 for (i = 1; i < (Word)(escn_symtab->szB/sizeof(ElfXX_Sym)); i++) {
825 ElfXX_Sym sym;
826 ML_(img_get)(&sym, escn_symtab->img,
827 escn_symtab->ioff + i * sizeof(ElfXX_Sym), sizeof(sym));
828 DiOffT sym_name = escn_strtab->ioff + sym.st_name;
829 Addr sym_svma = sym.st_value;
831 if (di->trace_symtab)
832 show_raw_elf_symbol(escn_strtab->img, i,
833 &sym, sym_name, sym_svma, False);
835 SymAVMAs sym_avmas_really;
836 Int sym_size = 0;
837 Bool from_opd = False, is_text = False, is_ifunc = False;
838 Bool is_global = False;
839 DiOffT sym_name_really = DiOffT_INVALID;
840 sym_avmas_really.main = 0;
841 SET_TOCPTR_AVMA(sym_avmas_really, 0);
842 SET_LOCAL_EP_AVMA(sym_avmas_really, 0);
843 if (get_elf_symbol_info(di, &sym, sym_name, escn_strtab,
844 sym_svma, symtab_in_debug,
845 escn_opd, di->text_bias,
846 &sym_name_really,
847 &sym_avmas_really,
848 &sym_size,
849 &from_opd, &is_text, &is_ifunc, &is_global)) {
851 DiSym disym;
852 VG_(memset)(&disym, 0, sizeof(disym));
853 HChar* cstr = ML_(img_strdup)(escn_strtab->img,
854 "di.res__n.1", sym_name_really);
855 disym.avmas = sym_avmas_really;
856 disym.pri_name = ML_(addStr) ( di, cstr, -1 );
857 disym.sec_names = NULL;
858 disym.size = sym_size;
859 disym.isText = is_text;
860 disym.isIFunc = is_ifunc;
861 disym.isGlobal = is_global;
862 if (cstr) { ML_(dinfo_free)(cstr); cstr = NULL; }
863 vg_assert(disym.pri_name);
864 vg_assert(GET_TOCPTR_AVMA(disym.avmas) == 0);
865 /* has no role except on ppc64be-linux */
866 ML_(addSym) ( di, &disym );
868 if (TRACE_SYMTAB_ENABLED) {
869 TRACE_SYMTAB(" rec(%c) [%4ld]: "
870 " val %#010lx, sz %4d %s\n",
871 is_text ? 't' : 'd',
873 disym.avmas.main,
874 (Int)disym.size,
875 disym.pri_name
877 if (GET_LOCAL_EP_AVMA(disym.avmas) != 0) {
878 TRACE_SYMTAB(" local entry point %#010lx\n",
879 GET_LOCAL_EP_AVMA(disym.avmas));
888 /* Read an ELF symbol table (normal or dynamic). This one is for
889 ppc64be-linux, which requires special treatment. */
891 typedef
892 struct {
893 Addr addr;
894 DiOffT name;
895 /* We have to store also the DiImage* so as to give context for
896 |name|. This is not part of the key (in terms of lookup) but
897 there's no easy other way to do this. Ugly. */
898 DiImage* img;
900 TempSymKey;
902 typedef
903 struct {
904 TempSymKey key;
905 Addr tocptr;
906 Int size;
907 Bool from_opd;
908 Bool is_text;
909 Bool is_ifunc;
910 Bool is_global;
912 TempSym;
914 static Word cmp_TempSymKey ( const TempSymKey* key1, const TempSym* elem2 )
916 /* Stay sane ... */
917 vg_assert(key1->img == elem2->key.img);
918 vg_assert(key1->img != NULL);
919 if (key1->addr < elem2->key.addr) return -1;
920 if (key1->addr > elem2->key.addr) return 1;
921 vg_assert(key1->name != DiOffT_INVALID);
922 vg_assert(elem2->key.name != DiOffT_INVALID);
923 return (Word)ML_(img_strcmp)(key1->img, key1->name, elem2->key.name);
926 static
927 __attribute__((unused)) /* not referred to on all targets */
928 void read_elf_symtab__ppc64be_linux(
929 struct _DebugInfo* di, const HChar* tab_name,
930 DiSlice* escn_symtab,
931 DiSlice* escn_strtab,
932 DiSlice* escn_opd, /* ppc64be-linux only */
933 Bool symtab_in_debug
936 Word i;
937 Int old_size;
938 Bool modify_size, modify_tocptr;
939 OSet *oset;
940 TempSymKey key;
941 TempSym *elem;
942 TempSym *prev;
944 if (escn_strtab->img == NULL || escn_symtab->img == NULL) {
945 HChar buf[VG_(strlen)(tab_name) + 40];
946 VG_(sprintf)(buf, " object doesn't have a %s", tab_name);
947 ML_(symerr)(di, False, buf);
948 return;
951 TRACE_SYMTAB("\n--- Reading (ELF, ppc64be-linux) %s (%llu entries) ---\n",
952 tab_name, escn_symtab->szB/sizeof(ElfXX_Sym) );
954 oset = VG_(OSetGen_Create)( offsetof(TempSym,key),
955 (OSetCmp_t)cmp_TempSymKey,
956 ML_(dinfo_zalloc), "di.respl.1",
957 ML_(dinfo_free) );
959 /* Perhaps should start at i = 1; ELF docs suggest that entry
960 0 always denotes 'unknown symbol'. */
961 for (i = 1; i < (Word)(escn_symtab->szB/sizeof(ElfXX_Sym)); i++) {
962 ElfXX_Sym sym;
963 ML_(img_get)(&sym, escn_symtab->img,
964 escn_symtab->ioff + i * sizeof(ElfXX_Sym), sizeof(sym));
965 DiOffT sym_name = escn_strtab->ioff + sym.st_name;
966 Addr sym_svma = sym.st_value;
968 if (di->trace_symtab)
969 show_raw_elf_symbol(escn_strtab->img, i,
970 &sym, sym_name, sym_svma, True);
972 SymAVMAs sym_avmas_really;
973 Int sym_size = 0;
974 Bool from_opd = False, is_text = False, is_ifunc = False;
975 Bool is_global = False;
976 DiOffT sym_name_really = DiOffT_INVALID;
977 DiSym disym;
978 VG_(memset)(&disym, 0, sizeof(disym));
979 sym_avmas_really.main = 0;
980 SET_TOCPTR_AVMA(sym_avmas_really, 0);
981 SET_LOCAL_EP_AVMA(sym_avmas_really, 0);
982 if (get_elf_symbol_info(di, &sym, sym_name, escn_strtab,
983 sym_svma, symtab_in_debug,
984 escn_opd, di->text_bias,
985 &sym_name_really,
986 &sym_avmas_really,
987 &sym_size,
988 &from_opd, &is_text, &is_ifunc, &is_global)) {
990 /* Check if we've seen this (name,addr) key before. */
991 key.addr = sym_avmas_really.main;
992 key.name = sym_name_really;
993 key.img = escn_strtab->img;
994 prev = VG_(OSetGen_Lookup)( oset, &key );
996 if (prev) {
998 /* Seen it before. Fold in whatever new info we can. */
999 modify_size = False;
1000 modify_tocptr = False;
1001 old_size = 0;
1003 if (prev->from_opd && !from_opd
1004 && (prev->size == 24 || prev->size == 16)
1005 && sym_size != prev->size) {
1006 /* Existing one is an opd-redirect, with a bogus size,
1007 so the only useful new fact we have is the real size
1008 of the symbol. */
1009 modify_size = True;
1010 old_size = prev->size;
1011 prev->size = sym_size;
1013 else
1014 if (!prev->from_opd && from_opd
1015 && (sym_size == 24 || sym_size == 16)) {
1016 /* Existing one is non-opd, new one is opd. What we
1017 can acquire from the new one is the TOC ptr to be
1018 used. Since the existing sym is non-toc, it
1019 shouldn't currently have an known TOC ptr. */
1020 vg_assert(prev->tocptr == 0);
1021 modify_tocptr = True;
1022 prev->tocptr = GET_TOCPTR_AVMA(sym_avmas_really);
1024 else {
1025 /* ignore. can we do better here? */
1028 /* Only one or the other is possible (I think) */
1029 vg_assert(!(modify_size && modify_tocptr));
1031 if (modify_size && di->trace_symtab) {
1032 VG_(printf)(" modify (old sz %4d) "
1033 " val %#010lx, toc %#010lx, sz %4d %llu\n",
1034 old_size,
1035 prev->key.addr,
1036 prev->tocptr,
1037 prev->size,
1038 prev->key.name
1041 if (modify_tocptr && di->trace_symtab) {
1042 VG_(printf)(" modify (upd tocptr) "
1043 " val %#010lx, toc %#010lx, sz %4d %llu\n",
1044 prev->key.addr,
1045 prev->tocptr,
1046 prev->size,
1047 prev->key.name
1051 } else {
1053 /* A new (name,addr) key. Add and continue. */
1054 elem = VG_(OSetGen_AllocNode)(oset, sizeof(TempSym));
1055 elem->key = key;
1056 elem->tocptr = GET_TOCPTR_AVMA(sym_avmas_really);
1057 elem->size = sym_size;
1058 elem->from_opd = from_opd;
1059 elem->is_text = is_text;
1060 elem->is_ifunc = is_ifunc;
1061 elem->is_global = is_global;
1062 VG_(OSetGen_Insert)(oset, elem);
1063 if (di->trace_symtab) {
1064 HChar* str = ML_(img_strdup)(escn_strtab->img, "di.respl.2",
1065 elem->key.name);
1066 VG_(printf)(" to-oset [%4ld]: "
1067 " val %#010lx, toc %#010lx, sz %4d %s\n",
1069 elem->key.addr,
1070 elem->tocptr,
1071 (Int) elem->size,
1074 if (str) ML_(dinfo_free)(str);
1081 /* All the syms that matter are in the oset. Now pull them out,
1082 build a "standard" symbol table, and nuke the oset. */
1084 i = 0;
1085 VG_(OSetGen_ResetIter)( oset );
1087 while ( (elem = VG_(OSetGen_Next)(oset)) ) {
1088 DiSym disym;
1089 VG_(memset)(&disym, 0, sizeof(disym));
1090 HChar* cstr = ML_(img_strdup)(escn_strtab->img,
1091 "di.res__ppc64.1", elem->key.name);
1092 disym.avmas.main = elem->key.addr;
1093 SET_TOCPTR_AVMA(disym.avmas, elem->tocptr);
1094 SET_LOCAL_EP_AVMA(disym.avmas, 0); // ppc64be does not use local_ep.
1095 disym.pri_name = ML_(addStr) ( di, cstr, -1 );
1096 disym.sec_names = NULL;
1097 disym.size = elem->size;
1098 disym.isText = elem->is_text;
1099 disym.isIFunc = elem->is_ifunc;
1100 disym.isGlobal = elem->is_global;
1101 ML_(dinfo_free)(cstr);
1102 vg_assert(disym.pri_name != NULL);
1104 ML_(addSym) ( di, &disym );
1105 if (di->trace_symtab) {
1106 VG_(printf)(" rec(%c%c%c) [%4ld]: "
1107 " val %#010lx, toc %#010lx, sz %4d %s\n",
1108 disym.isText ? 't' : 'd',
1109 disym.isIFunc ? 'i' : '-',
1110 disym.isGlobal ? 'g' : 'l',
1112 disym.avmas.main,
1113 GET_TOCPTR_AVMA(disym.avmas),
1114 (Int) disym.size,
1115 disym.pri_name
1118 i++;
1121 VG_(OSetGen_Destroy)( oset );
1124 #if defined(VGO_freebsd)
1127 * read_and_set_osrel
1129 * "osrel" is in an Elf note. It has values such as 1201000 for FreeBSD 12.1
1130 * Some of the behaviour related to SIGSEGV and SIGBUS signals depends on the
1131 * kernel reading this value.
1133 * However in the case of Valgrind, the host is strictly statically linked and
1134 * does not contain the NT_FREEBSD_ABI_TAG note. And even if it did, we want to
1135 * override the value with that of the guest.
1137 * At some later date we might want to look at the value of "fctl0" (note with the
1138 * NT_FREEBSD_FEATURE_CTL type). This seems to be related to Address Space Layout
1139 * Randomization. No hurry at the moment.
1141 * See /usr/src/sys/kern/imgact_elf.c for details on how the kernel reads these
1142 * notes.
1144 static
1145 void read_and_set_osrel(DiImage* img)
1147 if (is_elf_object_file_by_DiImage(img, False)) {
1148 Word i;
1150 ElfXX_Ehdr ehdr;
1151 ML_(img_get)(&ehdr, img, 0, sizeof(ehdr));
1153 /* only set osrel for executable files, not for subsequent shared libraries */
1154 if (ehdr.e_type != ET_EXEC) {
1155 return;
1158 /* Skip the phdrs when we have to search the shdrs. In separate
1159 .debug files the phdrs might not be valid (they are a copy of
1160 the main ELF file) and might trigger assertions when getting
1161 image notes based on them. */
1162 for (i = 0; i < ehdr.e_phnum; i++) {
1163 ElfXX_Phdr phdr;
1164 ML_(img_get)(&phdr, img,
1165 ehdr.e_phoff + i * ehdr.e_phentsize, sizeof(phdr));
1167 if (phdr.p_type == PT_NOTE) {
1168 ElfXX_Off note_ioff = phdr.p_offset;
1170 while (note_ioff < phdr.p_offset + phdr.p_filesz) {
1171 ElfXX_Nhdr note[2];
1172 ML_(img_get)(note, img, (DiOffT)note_ioff, sizeof(note));
1173 DiOffT name_ioff = note_ioff + sizeof(ElfXX_Nhdr);
1174 //DiOffT desc_ioff = name_ioff + ((note[0].n_namesz + 3) & ~3);
1175 if (ML_(img_strcmp_c)(img, name_ioff, "FreeBSD") == 0
1176 && note[0].n_type == VKI_NT_FREEBSD_ABI_TAG) {
1178 u_int32_t osrel = note[1].n_type;
1179 int name[4];
1180 name[0] = CTL_KERN;
1181 name[1] = KERN_PROC;
1182 name[2] = KERN_PROC_OSREL;
1183 name[3] = VG_(getpid)();
1184 SizeT newlen = sizeof(osrel);
1185 Int error = VG_(sysctl)(name, 4, NULL, NULL, &osrel, newlen);
1186 if (error == -1) {
1187 VG_(message)(Vg_DebugMsg, "Warning: failed to set osrel for current process with value %u\n", osrel);
1188 } else {
1189 if (VG_(clo_verbosity) > 1) {
1190 VG_(message)(Vg_DebugMsg, "Set osrel for current process with value %u\n", osrel);
1194 note_ioff = note_ioff + sizeof(ElfXX_Nhdr)
1195 + ((note[0].n_namesz + 3) & ~3)
1196 + ((note[0].n_descsz + 3) & ~3);
1203 #endif
1206 * Look for a build-id in an ELF image. The build-id specification
1207 * can be found here:
1209 * http://fedoraproject.org/wiki/RolandMcGrath/BuildID
1211 * Returned string must be freed by the caller.
1213 static
1214 HChar* find_buildid(DiImage* img, Bool rel_ok, Bool search_shdrs)
1216 HChar* buildid = NULL;
1218 # ifdef NT_GNU_BUILD_ID
1219 if (is_elf_object_file_by_DiImage(img, rel_ok)) {
1220 Word i;
1222 ElfXX_Ehdr ehdr;
1223 ML_(img_get)(&ehdr, img, 0, sizeof(ehdr));
1224 /* Skip the phdrs when we have to search the shdrs. In separate
1225 .debug files the phdrs might not be valid (they are a copy of
1226 the main ELF file) and might trigger assertions when getting
1227 image notes based on them. */
1228 for (i = 0; !search_shdrs && i < ehdr.e_phnum; i++) {
1229 ElfXX_Phdr phdr;
1230 ML_(img_get)(&phdr, img,
1231 ehdr.e_phoff + i * ehdr.e_phentsize, sizeof(phdr));
1233 if (phdr.p_type == PT_NOTE) {
1234 ElfXX_Off note_ioff = phdr.p_offset;
1236 while (note_ioff < phdr.p_offset + phdr.p_filesz) {
1237 ElfXX_Nhdr note;
1238 ML_(img_get)(&note, img, (DiOffT)note_ioff, sizeof(note));
1239 DiOffT name_ioff = note_ioff + sizeof(ElfXX_Nhdr);
1240 DiOffT desc_ioff = name_ioff + ((note.n_namesz + 3) & ~3);
1241 if (ML_(img_strcmp_c)(img, name_ioff, ELF_NOTE_GNU) == 0
1242 && note.n_type == NT_GNU_BUILD_ID) {
1243 buildid = ML_(dinfo_zalloc)("di.fbi.1",
1244 note.n_descsz * 2 + 1);
1245 Word j;
1246 for (j = 0; j < note.n_descsz; j++) {
1247 UChar desc_j = ML_(img_get_UChar)(img, desc_ioff + j);
1248 VG_(sprintf)(buildid + VG_(strlen)(buildid),
1249 "%02x", (UInt)desc_j);
1253 note_ioff = note_ioff + sizeof(ElfXX_Nhdr)
1254 + ((note.n_namesz + 3) & ~3)
1255 + ((note.n_descsz + 3) & ~3);
1260 /* Normally we would only search shdrs for ET_REL files, but when
1261 we search for a separate .debug file phdrs might not be there
1262 (they are never loaded) or have been corrupted, so try again
1263 against shdrs. */
1264 if (buildid || (!rel_ok && !search_shdrs))
1265 return buildid;
1267 for (i = 0; i < ehdr.e_shnum; i++) {
1268 ElfXX_Shdr shdr;
1269 ML_(img_get)(&shdr, img,
1270 ehdr.e_shoff + i * ehdr.e_shentsize, sizeof(shdr));
1272 if (shdr.sh_type == SHT_NOTE) {
1273 ElfXX_Off note_ioff = shdr.sh_offset;
1275 while (note_ioff < shdr.sh_offset + shdr.sh_size) {
1276 ElfXX_Nhdr note;
1277 ML_(img_get)(&note, img, (DiOffT)note_ioff, sizeof(note));
1278 DiOffT name_ioff = note_ioff + sizeof(ElfXX_Nhdr);
1279 DiOffT desc_ioff = name_ioff + ((note.n_namesz + 3) & ~3);
1281 if (ML_(img_strcmp_c)(img, name_ioff, ELF_NOTE_GNU) == 0
1282 && note.n_type == NT_GNU_BUILD_ID) {
1283 buildid = ML_(dinfo_zalloc)("di.fbi.2",
1284 note.n_descsz * 2 + 1);
1285 Word j;
1286 for (j = 0; j < note.n_descsz; j++) {
1287 UChar desc_j = ML_(img_get_UChar)(img, desc_ioff + j);
1288 VG_(sprintf)(buildid + VG_(strlen)(buildid),
1289 "%02x", (UInt)desc_j);
1293 note_ioff = note_ioff + sizeof(ElfXX_Nhdr)
1294 + ((note.n_namesz + 3) & ~3)
1295 + ((note.n_descsz + 3) & ~3);
1300 # endif /* def NT_GNU_BUILD_ID */
1302 return buildid;
1306 /* Try and open a separate debug file, ignoring any where the CRC does
1307 not match the value from the main object file. Returned DiImage
1308 must be discarded by the caller.
1310 If |serverAddr| is NULL, |name| is expected to be a fully qualified
1311 (absolute) path to the file in the local filesystem. If
1312 |serverAddr| is non-NULL, it is expected to be an IPv4 and port
1313 spec of the form "d.d.d.d:d" or "d.d.d.d", and |name| is expected
1314 to be a plain filename (no path components at all).
1316 static
1317 DiImage* open_debug_file( const HChar* name, const HChar* buildid, UInt crc,
1318 Bool rel_ok, const HChar* serverAddr )
1320 DiImage* dimg
1321 = serverAddr ? ML_(img_from_di_server)(name, serverAddr)
1322 : ML_(img_from_local_file)(name);
1323 if (dimg == NULL)
1324 return NULL;
1326 if (VG_(clo_verbosity) > 1) {
1327 if (serverAddr)
1328 VG_(message)(Vg_DebugMsg, " Considering %s on server %s ..\n",
1329 name, serverAddr);
1330 else
1331 VG_(message)(Vg_DebugMsg, " Considering %s ..\n", name);
1334 /* We will always check the crc if we have one (altfiles don't have one)
1335 for now because we might be opening the main file again by any other
1336 name, and that obviously also has the same buildid. More efficient
1337 would be an fstat bases check or a check that the file actually
1338 contains .debug* sections. */
1339 if (buildid && crc == 0) {
1340 HChar* debug_buildid = find_buildid(dimg, rel_ok, True);
1341 if (debug_buildid == NULL || VG_(strcmp)(buildid, debug_buildid) != 0) {
1342 ML_(img_done)(dimg);
1343 if (VG_(clo_verbosity) > 1)
1344 VG_(message)(Vg_DebugMsg,
1345 " .. build-id mismatch (found %s wanted %s)\n",
1346 (debug_buildid ? debug_buildid : "(null)"), buildid);
1347 ML_(dinfo_free)(debug_buildid);
1348 return NULL;
1350 ML_(dinfo_free)(debug_buildid);
1351 if (VG_(clo_verbosity) > 1)
1352 VG_(message)(Vg_DebugMsg, " .. build-id is valid\n");
1353 } else {
1354 UInt calccrc = ML_(img_calc_gnu_debuglink_crc32)(dimg);
1355 if (calccrc != crc) {
1356 ML_(img_done)(dimg);
1357 if (VG_(clo_verbosity) > 1)
1358 VG_(message)(Vg_DebugMsg,
1359 " .. CRC mismatch (computed %08x wanted %08x)\n", calccrc, crc);
1360 return NULL;
1363 if (VG_(clo_verbosity) > 1)
1364 VG_(message)(Vg_DebugMsg, " .. CRC is valid\n");
1367 return dimg;
1370 #if defined(VGO_linux)
1371 /* Return the path of the debuginfod-find executable. */
1372 static
1373 const HChar* debuginfod_find_path( void )
1375 static const HChar* path = (const HChar*) -1;
1377 if (path == (const HChar*) -1) {
1378 if (VG_(getenv)("DEBUGINFOD_URLS") == NULL
1379 || VG_(strcmp)("", VG_(getenv("DEBUGINFOD_URLS"))) == 0)
1380 path = NULL;
1381 else
1382 path = VG_(find_executable)("debuginfod-find");
1385 return path;
1388 /* Try to find a separate debug file with |buildid| via debuginfod. If found,
1389 return its DiImage. Searches for a local debuginfod-find executable and
1390 runs it in a child process in order to download the debug file. */
1391 static
1392 DiImage* find_debug_file_debuginfod( const HChar* objpath,
1393 HChar** debugpath,
1394 const HChar* buildid,
1395 const UInt crc, Bool rel_ok )
1397 # define BUF_SIZE 4096
1398 Int out_fds[2], err_fds[2]; /* pipe fds */
1399 DiImage* dimg = NULL; /* the img we found */
1400 HChar buf[BUF_SIZE]; /* executable output buffer */
1401 const HChar* path; /* executable path */
1402 SizeT len; /* number of bytes read int buf */
1403 Int ret; /* result of read call */
1405 if (buildid == NULL)
1406 return NULL;
1408 if ((path = debuginfod_find_path()) == NULL)
1409 return NULL;
1411 if (VG_(pipe)(out_fds) != 0
1412 || VG_(pipe)(err_fds) != 0)
1413 return NULL;
1415 if (VG_(clo_verbosity) > 1)
1416 VG_(umsg)("Downloading debug info for %s...\n", objpath);
1418 /* Run debuginfod-find to query servers for the debuginfo. */
1419 Int pid = VG_(fork)();
1420 if (pid == 0) {
1421 const HChar *argv[4] = { path, "debuginfo", buildid, (HChar*)0 };
1423 /* Redirect stdout and stderr */
1424 SysRes res = VG_(dup2)(out_fds[1], 1);
1425 if (sr_Res(res) < 0)
1426 VG_(exit)(1);
1428 res = VG_(dup2)(err_fds[1], 2);
1429 if (sr_Res(res) < 0)
1430 VG_(exit)(1);
1432 /* Disable extra stderr output since it does not play well with umesg */
1433 VG_(env_unsetenv)(VG_(client_envp), "DEBUGINFOD_VERBOSE", NULL);
1434 VG_(env_unsetenv)(VG_(client_envp), "DEBUGINFOD_PROGRESS", NULL);
1436 VG_(close)(out_fds[0]);
1437 VG_(close)(err_fds[0]);
1438 VG_(execv)(argv[0], argv);
1440 /* If we are still alive here, execv failed. */
1441 VG_(exit)(1);
1444 VG_(close)(out_fds[1]);
1445 VG_(close)(err_fds[1]);
1447 if (pid < 0) {
1448 if (VG_(clo_verbosity) > 1)
1449 VG_(umsg)("Server Error\n");
1450 goto out;
1452 VG_(waitpid)(pid, NULL, 0);
1454 /* Set dimg if download was successful. */
1455 len = 0;
1456 ret = -1;
1457 while (len >= 0 && len < BUF_SIZE) {
1458 ret = VG_(read)(out_fds[0], buf + len, BUF_SIZE - len);
1459 if (ret <= 0)
1460 break;
1461 len += ret;
1463 if (ret >= 0 && len > 0
1464 && buf[0] == '/' && buf[len-1] == '\n') {
1466 /* Remove newline from filename before trying to open debug file */
1467 buf[len-1] = '\0';
1468 dimg = open_debug_file(buf, buildid, crc, rel_ok, NULL);
1469 if (dimg != NULL) {
1470 /* Success */
1471 if (*debugpath)
1472 ML_(dinfo_free)(*debugpath);
1474 *debugpath = ML_(dinfo_strdup)("di.fdfd.1", buf);
1475 if (VG_(clo_verbosity) > 1)
1476 VG_(umsg)("Successfully downloaded debug file for %s\n",
1477 objpath);
1478 goto out;
1482 /* Download failed so try to print error message. */
1483 HChar* nl;
1484 if (VG_(read)(err_fds[0], buf, BUF_SIZE) > 0
1485 && (nl = VG_(strchr)(buf, '\n'))) {
1486 *nl = '\0';
1487 if (VG_(clo_verbosity) > 1)
1488 VG_(umsg)("%s\n", buf);
1489 } else
1490 if (VG_(clo_verbosity) > 1)
1491 VG_(umsg)("Server Error\n");
1493 out:
1494 VG_(close)(out_fds[0]);
1495 VG_(close)(err_fds[0]);
1496 return dimg;
1498 #endif
1500 /* Try to find a separate debug file for a given object file. If
1501 found, return its DiImage, which should be freed by the caller. If
1502 |buildid| is non-NULL, then a debug object matching it is
1503 acceptable. If |buildid| is NULL or doesn't specify a findable
1504 debug object, then we look in various places to find a file with
1505 the specified CRC. And if that doesn't work out then we give
1506 up. */
1507 static
1508 DiImage* find_debug_file( struct _DebugInfo* di,
1509 const HChar* objpath, const HChar* buildid,
1510 const HChar* debugname, UInt crc, Bool rel_ok )
1512 const HChar* extrapath = VG_(clo_extra_debuginfo_path);
1513 const HChar* serverpath = VG_(clo_debuginfo_server);
1515 DiImage* dimg = NULL; /* the img that we found */
1516 HChar* debugpath = NULL; /* where we found it */
1518 if (buildid != NULL) {
1519 debugpath = ML_(dinfo_zalloc)("di.fdf.1",
1520 VG_(strlen)(buildid) + 33);
1522 VG_(sprintf)(debugpath, "/usr/lib/debug/.build-id/%c%c/%s.debug",
1523 buildid[0], buildid[1], buildid + 2);
1525 dimg = open_debug_file(debugpath, buildid, 0, rel_ok, NULL);
1526 if (!dimg) {
1527 ML_(dinfo_free)(debugpath);
1528 debugpath = NULL;
1532 if (dimg == NULL && debugname != NULL) {
1533 HChar *objdir = ML_(dinfo_strdup)("di.fdf.2", objpath);
1534 HChar *usrmerge_objdir;
1535 HChar *objdirptr;
1537 if ((objdirptr = VG_(strrchr)(objdir, '/')) != NULL)
1538 *objdirptr = '\0';
1540 if ((objdirptr = VG_(strstr)(objdir, "usr")) != NULL)
1541 usrmerge_objdir = objdirptr + VG_(strlen)("usr");
1542 else
1543 usrmerge_objdir = NULL;
1545 debugpath = ML_(dinfo_zalloc)(
1546 "di.fdf.3",
1547 VG_(strlen)(objdir) + VG_(strlen)(debugname) + 64
1548 + (extrapath ? VG_(strlen)(extrapath) : 0)
1549 + (serverpath ? VG_(strlen)(serverpath) : 0));
1551 # define TRY_OBJDIR(format, ...) \
1552 do { \
1553 VG_(sprintf)(debugpath, format, __VA_ARGS__); \
1554 dimg = open_debug_file(debugpath, buildid, crc, rel_ok, NULL); \
1555 if (dimg != NULL) goto dimg_ok; \
1556 } while (0);
1558 # define TRY_OBJDIR_USRMERGE_OBJDIR(format) \
1559 do { \
1560 TRY_OBJDIR(format, objdir, debugname); \
1561 if (usrmerge_objdir != NULL) { \
1562 TRY_OBJDIR(format, usrmerge_objdir, debugname); \
1564 } while (0)
1566 if (debugname[0] == '/') {
1567 TRY_OBJDIR("%s", debugname);
1570 TRY_OBJDIR_USRMERGE_OBJDIR("%s/%s");
1571 TRY_OBJDIR_USRMERGE_OBJDIR("%s/.debug/%s");
1572 TRY_OBJDIR_USRMERGE_OBJDIR("/usr/lib/debug%s/%s");
1574 if (extrapath) {
1575 TRY_OBJDIR("%s%s/%s", extrapath, objdir, debugname);
1576 if (usrmerge_objdir != NULL)
1577 TRY_OBJDIR("%s%s/%s", extrapath, usrmerge_objdir, debugname);
1579 # undef TRY_OBJDIR
1580 # undef TRY_OBJDIRS
1582 if (serverpath) {
1583 /* When looking on the debuginfo server, always just pass the
1584 basename. */
1585 const HChar* basename = debugname;
1586 if (VG_(strstr)(basename, "/") != NULL) {
1587 basename = VG_(strrchr)(basename, '/') + 1;
1589 VG_(sprintf)(debugpath, "%s on %s", basename, serverpath);
1590 dimg = open_debug_file(basename, buildid, crc, rel_ok, serverpath);
1591 if (dimg) goto dimg_ok;
1594 dimg_ok:
1596 ML_(dinfo_free)(objdir);
1599 # if defined(VGO_linux)
1600 if (VG_(clo_enable_debuginfod) && dimg == NULL)
1601 dimg = find_debug_file_debuginfod(objpath, &debugpath, buildid, crc, rel_ok);
1602 # endif
1604 if (dimg != NULL) {
1605 vg_assert(debugpath);
1606 TRACE_SYMTAB("\n");
1607 TRACE_SYMTAB("------ Found a debuginfo file: %s\n", debugpath);
1609 /* Only set once, we might be called again for opening the altfile. */
1610 if (di->fsm.dbgname == NULL)
1611 di->fsm.dbgname = ML_(dinfo_strdup)("di.fdf.4", debugpath);
1614 if (debugpath)
1615 ML_(dinfo_free)(debugpath);
1617 return dimg;
1621 /* Try to find a separate debug file for a given object file, in a
1622 hacky and dangerous way: check only the --extra-debuginfo-path and
1623 the --debuginfo-server. And don't do a consistency check. */
1624 static
1625 DiImage* find_debug_file_ad_hoc( const DebugInfo* di,
1626 const HChar* objpath )
1628 const HChar* extrapath = VG_(clo_extra_debuginfo_path);
1629 const HChar* serverpath = VG_(clo_debuginfo_server);
1631 DiImage* dimg = NULL; /* the img that we found */
1632 HChar* debugpath = NULL; /* where we found it */
1634 HChar *objdir = ML_(dinfo_strdup)("di.fdfah.1", objpath);
1635 HChar *objdirptr;
1637 if ((objdirptr = VG_(strrchr)(objdir, '/')) != NULL)
1638 *objdirptr = '\0';
1640 debugpath = ML_(dinfo_zalloc)(
1641 "di.fdfah.3",
1642 VG_(strlen)(objdir) + 64
1643 + (extrapath ? VG_(strlen)(extrapath) : 0)
1644 + (serverpath ? VG_(strlen)(serverpath) : 0));
1646 if (extrapath) {
1647 VG_(sprintf)(debugpath, "%s/%s", extrapath, objpath);
1648 dimg = ML_(img_from_local_file)(debugpath);
1649 if (dimg != NULL) {
1650 if (VG_(clo_verbosity) > 1) {
1651 VG_(message)(Vg_DebugMsg, " Using (POSSIBLY MISMATCHED) %s\n",
1652 debugpath);
1654 goto dimg_ok;
1657 if (serverpath) {
1658 /* When looking on the debuginfo server, always just pass the
1659 basename. */
1660 const HChar* basename = objpath;
1661 if (VG_(strstr)(basename, "/") != NULL) {
1662 basename = VG_(strrchr)(basename, '/') + 1;
1664 VG_(sprintf)(debugpath, "%s on %s", basename, serverpath);
1665 dimg = ML_(img_from_di_server)(basename, serverpath);
1666 if (dimg != NULL) {
1667 if (VG_(clo_verbosity) > 1) {
1668 VG_(message)(Vg_DebugMsg, " Using (POSSIBLY MISMATCHED) %s\n",
1669 debugpath);
1671 goto dimg_ok;
1675 dimg_ok:
1677 ML_(dinfo_free)(objdir);
1679 if (dimg != NULL) {
1680 vg_assert(debugpath);
1681 TRACE_SYMTAB("\n");
1682 TRACE_SYMTAB("------ Found an ad_hoc debuginfo file: %s\n", debugpath);
1685 if (debugpath)
1686 ML_(dinfo_free)(debugpath);
1688 return dimg;
1692 static DiOffT INDEX_BIS ( DiOffT base, UWord idx, UWord scale ) {
1693 // This is a bit stupid. Really, idx and scale ought to be
1694 // 64-bit quantities, always.
1695 return base + (DiOffT)idx * (DiOffT)scale;
1699 /* Find the file offset corresponding to SVMA by using the program
1700 headers. This is taken from binutils-2.17/binutils/readelf.c
1701 offset_from_vma(). */
1702 static
1703 Word file_offset_from_svma ( /*OUT*/Bool* ok,
1704 Addr svma,
1705 DiImage* img,
1706 DiOffT phdr_ioff,
1707 Word phdr_nent,
1708 Word phdr_ent_szB )
1710 Word i;
1711 for (i = 0; i < phdr_nent; i++) {
1712 ElfXX_Phdr seg;
1713 ML_(img_get)(&seg, img,
1714 INDEX_BIS(phdr_ioff, i, phdr_ent_szB), sizeof(seg));
1715 if (seg.p_type != PT_LOAD)
1716 continue;
1717 if (svma >= (seg.p_vaddr & -seg.p_align)
1718 && svma + 1 <= seg.p_vaddr + seg.p_filesz) {
1719 *ok = True;
1720 return svma - seg.p_vaddr + seg.p_offset;
1723 *ok = False;
1724 return 0;
1727 /* Check if section is compressed and modify DiSlice if it is.
1728 Returns False in case of unsupported compression type.
1730 static Bool check_compression(ElfXX_Shdr* h, DiSlice* s) {
1731 if (h->sh_flags & SHF_COMPRESSED) {
1732 ElfXX_Chdr chdr;
1733 ML_(img_get)(&chdr, s->img, s->ioff, sizeof(ElfXX_Chdr));
1734 if (chdr.ch_type != ELFCOMPRESS_ZLIB)
1735 return False;
1736 s->ioff = ML_(img_mark_compressed_part)(s->img,
1737 s->ioff + sizeof(ElfXX_Chdr),
1738 s->szB - sizeof(ElfXX_Chdr),
1739 (SizeT)chdr.ch_size);
1740 s->szB = chdr.ch_size;
1741 } else if (h->sh_size > SIZE_OF_ZLIB_HEADER) {
1742 /* Read the zlib header. In this case, it should be "ZLIB"
1743 followed by the uncompressed section size, 8 bytes in BE order. */
1744 UChar tmp[SIZE_OF_ZLIB_HEADER];
1745 ML_(img_get)(tmp, s->img, s->ioff, SIZE_OF_ZLIB_HEADER);
1746 if (VG_(memcmp)(tmp, "ZLIB", 4) == 0) {
1747 SizeT size;
1748 # if (VG_WORDSIZE == 8)
1749 size = tmp[4]; size <<= 8;
1750 size += tmp[5]; size <<= 8;
1751 size += tmp[6]; size <<= 8;
1752 size += tmp[7]; size <<= 8;
1753 # else
1754 vg_assert((tmp[4] == 0) && (tmp[5] == 0) && (tmp[6] == 0)
1755 && (tmp[7] == 0));
1756 size = 0;
1757 # endif
1758 size += tmp[8]; size <<= 8;
1759 size += tmp[9]; size <<= 8;
1760 size += tmp[10]; size <<= 8;
1761 size += tmp[11];
1762 s->ioff = ML_(img_mark_compressed_part)(s->img,
1763 s->ioff + SIZE_OF_ZLIB_HEADER,
1764 s->szB - SIZE_OF_ZLIB_HEADER,
1765 size);
1766 s->szB = size;
1769 return True;
1772 /* Helper function to get the readlink path. Returns a copy of path if the
1773 file wasn't a symbolic link. Returns NULL on error. Unless NULL is
1774 returned the result needs to be released with dinfo_free.
1776 static HChar* readlink_path (const HChar *path)
1778 SizeT bufsiz = VG_(strlen)(path);
1779 HChar *buf = ML_(dinfo_strdup)("readlink_path.strdup", path);
1780 UInt tries = 6;
1782 while (tries > 0) {
1783 SysRes res;
1784 #if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
1785 res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD,
1786 (UWord)path, (UWord)buf, bufsiz);
1787 #elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
1788 res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz);
1789 #elif defined(VGO_solaris)
1790 res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD, (UWord)path,
1791 (UWord)buf, bufsiz);
1792 #else
1793 # error Unknown OS
1794 #endif
1795 if (sr_isError(res)) {
1796 if (sr_Err(res) == VKI_EINVAL)
1797 return buf; // It wasn't a symbolic link, return the strdup result.
1798 ML_(dinfo_free)(buf);
1799 return NULL;
1802 SSizeT r = sr_Res(res);
1803 if (r < 0) break;
1804 if (r == bufsiz) { // buffer too small; increase and retry
1805 bufsiz *= 2 + 16;
1806 buf = ML_(dinfo_realloc)("readlink_path.realloc", buf, bufsiz);
1807 tries--;
1808 continue;
1810 buf[r] = '\0';
1811 break;
1814 if (tries == 0) { // We tried, but weird long path?
1815 ML_(dinfo_free)(buf);
1816 return NULL;
1819 if (buf[0] == '/')
1820 return buf;
1822 /* Relative path, add link dir. */
1823 HChar *linkdirptr;
1824 SizeT linkdir_len = VG_(strlen)(path);
1825 if ((linkdirptr = VG_(strrchr)(path, '/')) != NULL)
1826 linkdir_len -= VG_(strlen)(linkdirptr + 1);
1828 SizeT buflen = VG_(strlen)(buf);
1829 SizeT needed = linkdir_len + buflen + 1;
1830 if (bufsiz < needed)
1831 buf = ML_(dinfo_realloc)("readlink_path.linkdir", buf, needed);
1833 VG_(memmove)(buf + linkdir_len, buf, buflen);
1834 VG_(memcpy)(buf, path, linkdir_len);
1835 buf[needed - 1] = '\0';
1837 return buf;
1840 #define FINDX_MIMG(_sec_name, _sec_escn, _post_fx) \
1841 do { \
1842 ElfXX_Shdr a_shdr; \
1843 ML_(img_get)(&a_shdr, mimg, \
1844 INDEX_BIS(shdr_mioff, i, shdr_ment_szB), \
1845 sizeof(a_shdr)); \
1846 if (0 == ML_(img_strcmp_c)(mimg, shdr_strtab_mioff \
1847 + a_shdr.sh_name, _sec_name)) { \
1848 Bool nobits; \
1849 _sec_escn.img = mimg; \
1850 _sec_escn.ioff = (DiOffT)a_shdr.sh_offset; \
1851 _sec_escn.szB = a_shdr.sh_size; \
1852 if (!check_compression(&a_shdr, &_sec_escn)) { \
1853 ML_(symerr)(di, True, " Compression type is unsupported"); \
1854 goto out; \
1856 nobits = a_shdr.sh_type == SHT_NOBITS; \
1857 vg_assert(_sec_escn.img != NULL); \
1858 vg_assert(_sec_escn.ioff != DiOffT_INVALID); \
1859 TRACE_SYMTAB( "%-18s: ioff %llu .. %llu\n", \
1860 _sec_name, (ULong)a_shdr.sh_offset, \
1861 ((ULong)a_shdr.sh_offset) + a_shdr.sh_size - 1); \
1862 /* SHT_NOBITS sections have zero size in the file. */ \
1863 if (!nobits && \
1864 a_shdr.sh_offset + \
1865 a_shdr.sh_size > ML_(img_real_size)(mimg)) { \
1866 ML_(symerr)(di, True, \
1867 " section beyond image end?!"); \
1868 goto out; \
1870 _post_fx; \
1872 } while (0);
1874 /* Version with no post-effects */
1875 #define FIND_MIMG(_sec_name, _sec_escn) \
1876 FINDX_MIMG(_sec_name, _sec_escn, /**/)
1878 /* The central function for reading ELF debug info. For the
1879 object/exe specified by the DebugInfo, find ELF sections, then read
1880 the symbols, line number info, file name info, CFA (stack-unwind
1881 info) and anything else we want, into the tables within the
1882 supplied DebugInfo.
1885 Bool ML_(read_elf_object) ( struct _DebugInfo* di )
1887 /* This function is long and complex. That, and the presence of
1888 nested scopes, means it's not always easy to see which parts are
1889 in loops/conditionals and which aren't. To make it easier to
1890 follow, points executed exactly once -- that is, those which are
1891 the top level of the function -- are marked TOPLEVEL.
1893 /* Consistent terminology for local variable names, without which
1894 it's almost unfollowably complex:
1896 In which file?
1897 in the main ELF file *_m*
1898 in the debuginfo file *_d*
1899 in the alt debuginfo file *_a*
1901 What kind of thing?
1902 _{m,d,a}img a DiImage*
1903 _{m,d,a}ioff an offset in the image (DiOffT)
1904 _{m,d,a}nent "number of entries"
1905 _{m,d,a}ent_szB "size in bytes of an entry"
1906 ehdr_{m,d,a} ELF header
1907 phdr Program header
1908 shdr Section header
1909 a_X a temporary X
1910 _escn an DiSlice (elf section info) variable
1911 szB size in bytes
1915 /* TOPLEVEL */
1916 Bool ok;
1917 Word i, j;
1918 Bool dynbss_present = False;
1919 Bool sdynbss_present = False;
1920 Bool retval = False;
1922 /* Image for the main ELF file we're working with. */
1923 DiImage* mimg = NULL;
1925 /* ELF header offset for the main file. Should be zero since the
1926 ELF header is at start of file. */
1927 DiOffT ehdr_mioff = 0;
1929 /* Program header table image addr, # entries, entry size */
1930 DiOffT phdr_mioff = 0;
1931 UWord phdr_mnent = 0;
1932 UWord phdr_ment_szB = 0;
1934 /* Section header image addr, # entries, entry size. Also the
1935 associated string table. */
1936 DiOffT shdr_mioff = 0;
1937 UWord shdr_mnent = 0;
1938 UWord shdr_ment_szB = 0;
1939 DiOffT shdr_strtab_mioff = 0;
1941 /* SVMAs covered by rx and rw segments and corresponding biases.
1942 Normally each object would provide just one rx and one rw area,
1943 but various ELF mangling tools create objects with multiple
1944 such entries, hence the generality. */
1945 typedef
1946 struct {
1947 Addr svma_base;
1948 Addr svma_limit;
1949 PtrdiffT bias;
1950 Bool exec;
1952 RangeAndBias;
1954 XArray* /* of RangeAndBias */ svma_ranges = NULL;
1956 # if defined(SOLARIS_PT_SUNDWTRACE_THRP)
1957 Addr dtrace_data_vaddr = 0;
1958 # endif
1960 vg_assert(di);
1961 vg_assert(di->fsm.have_rx_map == True);
1962 vg_assert(di->fsm.rw_map_count >= 1);
1963 vg_assert(di->have_dinfo == False);
1964 vg_assert(di->fsm.filename);
1965 vg_assert(!di->symtab);
1966 vg_assert(!di->loctab);
1967 vg_assert(!di->inltab);
1968 vg_assert(!di->cfsi_base);
1969 vg_assert(!di->cfsi_m_ix);
1970 vg_assert(!di->cfsi_rd);
1971 vg_assert(!di->cfsi_exprs);
1972 vg_assert(!di->strpool);
1973 vg_assert(!di->fndnpool);
1974 vg_assert(!di->soname);
1977 Bool has_nonempty_rx = False;
1978 Bool has_nonempty_rw = False;
1979 for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
1980 DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
1981 if (!map->rx && !map->rw)
1982 continue;
1983 if (map->rx && map->size > 0)
1984 has_nonempty_rx = True;
1985 if (map->rw && map->size > 0)
1986 has_nonempty_rw = True;
1987 /* If this doesn't hold true, it means that m_syswrap/m_aspacemgr
1988 managed to do a mapping where the start isn't page aligned.
1989 Which sounds pretty bogus to me. */
1990 vg_assert(VG_IS_PAGE_ALIGNED(map->avma));
1992 vg_assert(has_nonempty_rx);
1993 vg_assert(has_nonempty_rw);
1996 /* ----------------------------------------------------------
1997 At this point, there is very little information in the
1998 DebugInfo. We only know that something that looks like an ELF
1999 file has been mapped rx-ishly and rw-ishly as recorded in the
2000 di->fsm.maps array items. First we examine the file's ELF
2001 Program Header, and, by comparing that against the di->fsm.maps
2002 info, try to figure out the AVMAs for the sections we care
2003 about, that should have been mapped: text, data, sdata, bss,
2004 got, plt, and toc.
2005 ---------------------------------------------------------- */
2007 if (VG_(clo_verbosity) > 1 || VG_(clo_trace_redir))
2008 VG_(message)(Vg_DebugMsg, "Reading syms from %s\n",
2009 di->fsm.filename );
2011 /* Connect to the primary object image, so that we can read symbols
2012 and line number info out of it. It will be disconnected
2013 immediately thereafter; it is only connected transiently. */
2014 mimg = ML_(img_from_local_file)(di->fsm.filename);
2015 if (mimg == NULL) {
2016 VG_(message)(Vg_UserMsg, "warning: connection to image %s failed\n",
2017 di->fsm.filename );
2018 VG_(message)(Vg_UserMsg, " no symbols or debug info loaded\n" );
2019 return False;
2022 /* Ok, the object image is available. Now verify that it is a
2023 valid ELF .so or executable image. */
2024 ok = is_elf_object_file_by_DiImage(mimg, False);
2025 if (!ok) {
2026 ML_(symerr)(di, True, "Invalid ELF Header");
2027 goto out;
2030 /* Find where the program and section header tables are, and give
2031 up if either is missing or outside the image (bogus). */
2032 ElfXX_Ehdr ehdr_m;
2033 vg_assert(ehdr_mioff == 0); // ensured by its initialisation
2034 ok = ML_(img_valid)(mimg, ehdr_mioff, sizeof(ehdr_m));
2035 vg_assert(ok); // ML_(is_elf_object_file) should ensure this
2036 ML_(img_get)(&ehdr_m, mimg, ehdr_mioff, sizeof(ehdr_m));
2038 phdr_mioff = ehdr_mioff + ehdr_m.e_phoff;
2039 phdr_mnent = ehdr_m.e_phnum;
2040 phdr_ment_szB = ehdr_m.e_phentsize;
2042 shdr_mioff = ehdr_mioff + ehdr_m.e_shoff;
2043 shdr_mnent = ehdr_m.e_shnum;
2044 shdr_ment_szB = ehdr_m.e_shentsize;
2046 TRACE_SYMTAB("------ Basic facts about the object ------\n");
2047 TRACE_SYMTAB("object: n_oimage %llu\n",
2048 (ULong)ML_(img_size)(mimg));
2049 TRACE_SYMTAB("phdr: ioff %llu nent %lu ent_szB %lu\n",
2050 phdr_mioff, phdr_mnent, phdr_ment_szB);
2051 TRACE_SYMTAB("shdr: ioff %llu nent %lu ent_szB %lu\n",
2052 shdr_mioff, shdr_mnent, shdr_ment_szB);
2053 for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
2054 const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
2055 if (map->rx)
2056 TRACE_SYMTAB("rx_map: avma %#lx size %lu foff %lld\n",
2057 map->avma, map->size, (Long)map->foff);
2059 for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
2060 const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
2061 if (map->rw)
2062 TRACE_SYMTAB("rw_map: avma %#lx size %lu foff %lld\n",
2063 map->avma, map->size, (Long)map->foff);
2066 if (phdr_mnent == 0
2067 || !ML_(img_valid)(mimg, phdr_mioff, phdr_mnent * phdr_ment_szB)) {
2068 ML_(symerr)(di, True, "Missing or invalid ELF Program Header Table");
2069 goto out;
2072 if (shdr_mnent == 0
2073 || !ML_(img_valid)(mimg, shdr_mioff, shdr_mnent * shdr_ment_szB)) {
2074 ML_(symerr)(di, True, "Missing or invalid ELF Section Header Table");
2075 goto out;
2078 /* Also find the section header's string table, and validate. */
2079 /* checked previously by is_elf_object_file: */
2080 vg_assert(ehdr_m.e_shstrndx != SHN_UNDEF);
2082 // shdr_mioff is the offset of the section header table
2083 // and we need the ehdr_m.e_shstrndx'th entry
2084 { ElfXX_Shdr a_shdr;
2085 ML_(img_get)(&a_shdr, mimg,
2086 INDEX_BIS(shdr_mioff, ehdr_m.e_shstrndx, shdr_ment_szB),
2087 sizeof(a_shdr));
2088 shdr_strtab_mioff
2089 = ehdr_mioff /* isn't this always zero? */ + a_shdr.sh_offset;
2091 if (!ML_(img_valid)(mimg, shdr_strtab_mioff,
2092 1/*bogus, but we don't know the real size*/ )) {
2093 ML_(symerr)(di, True, "Invalid ELF Section Header String Table");
2094 goto out;
2098 TRACE_SYMTAB("shdr: string table at %llu\n", shdr_strtab_mioff);
2100 svma_ranges = VG_(newXA)(ML_(dinfo_zalloc), "di.relfdi.1",
2101 ML_(dinfo_free), sizeof(RangeAndBias));
2103 /* TOPLEVEL */
2104 /* Look through the program header table, and:
2105 - copy information from suitable PT_LOAD entries into svma_ranges
2106 - find (or fake up) the .soname for this object.
2108 TRACE_SYMTAB("\n");
2109 TRACE_SYMTAB("------ Examining the program headers ------\n");
2110 vg_assert(di->soname == NULL);
2112 /* TOPLEVEL */
2113 ElfXX_Addr prev_svma = 0;
2115 for (i = 0; i < phdr_mnent; i++) {
2116 ElfXX_Phdr a_phdr;
2117 ML_(img_get)(&a_phdr, mimg,
2118 INDEX_BIS(phdr_mioff, i, phdr_ment_szB),
2119 sizeof(a_phdr));
2121 /* Make sure the PT_LOADable entries are in order and
2122 non-overlapping. This in turn means the address ranges
2123 slurped into svma_ranges are in order and
2124 non-overlapping. */
2126 if (a_phdr.p_type == PT_LOAD) {
2127 TRACE_SYMTAB("PT_LOAD[%ld]: p_vaddr %#lx (prev %#lx)\n",
2128 i, (UWord)a_phdr.p_vaddr, (UWord)prev_svma);
2129 TRACE_SYMTAB("PT_LOAD[%ld]: p_offset %lu, p_filesz %lu,"
2130 " perms %c%c%c\n",
2131 i, (UWord)a_phdr.p_offset, (UWord)a_phdr.p_filesz,
2132 a_phdr.p_flags & PF_R ? 'r' : '-',
2133 a_phdr.p_flags & PF_W ? 'w' : '-',
2134 a_phdr.p_flags & PF_X ? 'x' : '-');
2135 if (a_phdr.p_vaddr < prev_svma) {
2136 ML_(symerr)(di, True,
2137 "ELF Program Headers are not in ascending order");
2138 goto out;
2140 prev_svma = a_phdr.p_vaddr;
2141 if (a_phdr.p_memsz > 0) {
2142 Bool loaded = False;
2143 for (j = 0; j < VG_(sizeXA)(di->fsm.maps); j++) {
2144 const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, j);
2145 Bool offset_checks = a_phdr.p_offset >= map->foff
2146 && a_phdr.p_offset < map->foff + map->size
2147 && a_phdr.p_offset + a_phdr.p_filesz <= map->foff + map->size;
2148 #if defined(VGO_freebsd)
2150 * One special case where we can't get an accurate value
2151 * for the offset - the RW segment of the tool itself.
2152 * See aspacemgr-linux.c parse_procselfmaps()
2154 if (map->ignore_foff) {
2155 offset_checks = True;
2157 #endif
2158 if ( (map->rx || map->rw || map->ro)
2159 && map->size > 0 /* stay sane */
2160 && offset_checks) {
2161 RangeAndBias item;
2162 item.svma_base = a_phdr.p_vaddr;
2163 item.svma_limit = a_phdr.p_vaddr + a_phdr.p_memsz;
2164 item.bias = map->avma - map->foff
2165 + a_phdr.p_offset - a_phdr.p_vaddr;
2166 if (map->rw
2167 && (a_phdr.p_flags & (PF_R | PF_W))
2168 == (PF_R | PF_W)) {
2169 item.exec = False;
2170 VG_(addToXA)(svma_ranges, &item);
2171 TRACE_SYMTAB(
2172 "PT_LOAD[%ld]: acquired as rw, bias 0x%lx\n",
2173 i, (UWord)item.bias);
2174 loaded = True;
2176 if (map->rx
2177 && (a_phdr.p_flags & (PF_R | PF_X))
2178 == (PF_R | PF_X)) {
2179 item.exec = True;
2180 VG_(addToXA)(svma_ranges, &item);
2181 TRACE_SYMTAB(
2182 "PT_LOAD[%ld]: acquired as rx, bias 0x%lx\n",
2183 i, (UWord)item.bias);
2184 loaded = True;
2186 if (map->ro
2187 && (a_phdr.p_flags & (PF_R | PF_W | PF_X))
2188 == PF_R) {
2189 item.exec = False;
2190 VG_(addToXA)(svma_ranges, &item);
2191 TRACE_SYMTAB(
2192 "PT_LOAD[%ld]: acquired as ro, bias 0x%lx\n",
2193 i, (UWord)item.bias);
2194 loaded = True;
2198 if (!loaded) {
2199 # if defined(SOLARIS_PT_SUNDWTRACE_THRP)
2200 if ((a_phdr.p_memsz == VKI_PT_SUNWDTRACE_SIZE)
2201 && ((a_phdr.p_flags & (PF_R | PF_W | PF_X)) == PF_R)) {
2202 TRACE_SYMTAB("PT_LOAD[%ld]: ignore dtrace_data program "
2203 "header\n", i);
2204 dtrace_data_vaddr = a_phdr.p_vaddr;
2205 continue;
2207 # endif /* SOLARIS_PT_SUNDWTRACE_THRP */
2209 ML_(symerr)(di, False,
2210 "ELF section outside all mapped regions");
2211 /* This problem might be solved by further memory mappings.
2212 Avoid the vg_assert(!di->soname) at the beginning of this
2213 function if DYNAMIC section has been already processed. */
2214 if (di->soname) {
2215 ML_(dinfo_free)(di->soname);
2216 di->soname = NULL;
2218 goto out;
2223 /* Try to get the soname. If there isn't one, use "NONE".
2224 The seginfo needs to have some kind of soname in order to
2225 facilitate writing redirect functions, since all redirect
2226 specifications require a soname (pattern). */
2227 if (a_phdr.p_type == PT_DYNAMIC && di->soname == NULL) {
2228 Word stroff = -1;
2229 DiOffT strtab_mioff = DiOffT_INVALID;
2230 for (j = 0; True/*exit check is in the loop*/; j++) {
2231 ElfXX_Dyn t_dyn_m; /* dyn_img[j] */
2232 ML_(img_get)(&t_dyn_m, mimg,
2233 INDEX_BIS(ehdr_mioff + a_phdr.p_offset,
2234 j, sizeof(ElfXX_Dyn)),
2235 sizeof(t_dyn_m));
2236 if (t_dyn_m.d_tag == DT_NULL)
2237 break;
2239 switch (t_dyn_m.d_tag) {
2240 case DT_SONAME: {
2241 stroff = t_dyn_m.d_un.d_val;
2242 break;
2244 case DT_STRTAB: {
2245 Bool ok2 = False;
2246 Word offset = file_offset_from_svma(
2247 &ok2, t_dyn_m.d_un.d_ptr, mimg,
2248 phdr_mioff, phdr_mnent, phdr_ment_szB
2250 if (ok2 && strtab_mioff == DiOffT_INVALID) {
2251 // Check for obviously bogus offsets.
2252 if (!ML_(img_valid)(mimg, offset, 1)) {
2253 ML_(symerr)(di, True, "Invalid DT_STRTAB offset");
2254 goto out;
2256 strtab_mioff = ehdr_mioff + offset;
2257 vg_assert(ehdr_mioff == 0); // should always be
2259 break;
2261 default:
2262 break;
2265 if (stroff != -1 && strtab_mioff != DiOffT_INVALID) {
2266 di->soname = ML_(img_strdup)(mimg, "di.redi.1",
2267 strtab_mioff + stroff);
2268 TRACE_SYMTAB("Found soname = %s\n", di->soname);
2271 } /* for (i = 0; i < phdr_Mnent; i++) ... */
2272 /* TOPLEVEL */
2274 } /* examine the program headers (local scope) */
2276 /* TOPLEVEL */
2278 /* If, after looking at all the program headers, we still didn't
2279 find a soname, add a fake one. */
2280 if (di->soname == NULL) {
2281 TRACE_SYMTAB("No soname found; using (fake) \"NONE\"\n");
2282 di->soname = ML_(dinfo_strdup)("di.redi.2", "NONE");
2285 vg_assert(VG_(sizeXA)(svma_ranges) != 0);
2287 /* Now read the section table. */
2288 TRACE_SYMTAB("\n");
2289 TRACE_SYMTAB("------ Examining the section headers ------\n");
2290 for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
2291 const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
2292 if (map->rx)
2293 TRACE_SYMTAB("rx: at %#lx are mapped foffsets %lld .. %lld\n",
2294 map->avma, (Long)map->foff, (Long)(map->foff + map->size - 1) );
2296 TRACE_SYMTAB("rx: contains these svma regions:\n");
2297 for (i = 0; i < VG_(sizeXA)(svma_ranges); i++) {
2298 const RangeAndBias* reg = VG_(indexXA)(svma_ranges, i);
2299 if (reg->exec)
2300 TRACE_SYMTAB(" svmas %#lx .. %#lx with bias %#lx\n",
2301 reg->svma_base, reg->svma_limit - 1, (UWord)reg->bias );
2303 for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
2304 const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
2305 if (map->rw) {
2306 TRACE_SYMTAB("rw: at %#lx are mapped foffsets %lld .. %lld\n",
2307 map->avma, (Long)map->foff, (Long)(map->foff + map->size - 1) );
2310 TRACE_SYMTAB("rw: contains these svma regions:\n");
2311 for (i = 0; i < VG_(sizeXA)(svma_ranges); i++) {
2312 const RangeAndBias* reg = VG_(indexXA)(svma_ranges, i);
2313 if (!reg->exec)
2314 TRACE_SYMTAB(" svmas %#lx .. %#lx with bias %#lx\n",
2315 reg->svma_base, reg->svma_limit - 1, (UWord)reg->bias );
2318 /* TOPLEVEL */
2319 /* Iterate over section headers */
2320 for (i = 0; i < shdr_mnent; i++) {
2321 ElfXX_Shdr a_shdr;
2322 ML_(img_get)(&a_shdr, mimg,
2323 INDEX_BIS(shdr_mioff, i, shdr_ment_szB), sizeof(a_shdr));
2324 DiOffT name_mioff = shdr_strtab_mioff + a_shdr.sh_name;
2325 HChar* name = ML_(img_strdup)(mimg, "di.redi_name.2", name_mioff);
2326 Addr svma = a_shdr.sh_addr;
2327 OffT foff = a_shdr.sh_offset;
2328 UWord size = a_shdr.sh_size; /* Do not change this to be signed. */
2329 UInt alyn = a_shdr.sh_addralign;
2330 Bool nobits = a_shdr.sh_type == SHT_NOBITS;
2331 /* Look through our collection of info obtained from the PT_LOAD
2332 headers, and make 'inrx' and 'inrw1' point to the first entry
2333 in each that intersects 'avma'. If in each case none is found,
2334 leave the relevant pointer at NULL. */
2335 RangeAndBias* inrx = NULL;
2336 RangeAndBias* inrw1 = NULL;
2337 /* Depending on the link editor there may be two RW PT_LOAD headers
2338 * If so this will point to the seond one */
2339 RangeAndBias* inrw2 = NULL;
2340 /* used to switch between inrw1 and inrw2 */
2341 RangeAndBias* inrw;
2343 for (j = 0; j < VG_(sizeXA)(svma_ranges); j++) {
2344 RangeAndBias* rng = VG_(indexXA)(svma_ranges, j);
2345 if (svma >= rng->svma_base && svma < rng->svma_limit) {
2346 if (!inrx && rng->exec) {
2347 inrx = rng;
2348 } else if (!inrw1 && !rng->exec) {
2349 inrw1 = rng;
2350 } else if (!inrw2 && !rng->exec) {
2351 inrw2 = rng;
2356 TRACE_SYMTAB(" [sec %2ld] %s %s %s al%4u foff %6lld .. %6lld "
2357 " svma %p name \"%s\"\n",
2358 i, inrx ? "rx" : " ", inrw1 ? "rw" : " ", inrw2 ? "rw" : " ",
2359 alyn, (Long) foff, (size == 0) ? (Long)foff : (Long)(foff+size-1),
2360 (void *) svma, name);
2362 /* Check for sane-sized segments. SHT_NOBITS sections have zero
2363 size in the file and their offsets are just conceptual. */
2364 if (!nobits &&
2365 (foff >= ML_(img_size)(mimg) || foff + size > ML_(img_size)(mimg))) {
2366 ML_(symerr)(di, True, "ELF Section extends beyond image end");
2367 goto out;
2370 /* Check for a sane alignment value. */
2371 if (alyn > 0 && -1 == VG_(log2)(alyn)) {
2372 ML_(symerr)(di, True, "ELF Section contains invalid "
2373 ".sh_addralign value");
2374 goto out;
2377 /* Ignore zero sized sections. */
2378 if (size == 0) {
2379 TRACE_SYMTAB("zero sized section \"%s\", ignoring\n", name);
2380 ML_(dinfo_free)(name);
2381 continue;
2384 # define BAD(_secname) \
2385 do { ML_(symerr)(di, True, \
2386 "Can't make sense of " _secname \
2387 " section mapping"); \
2388 /* make sure we don't assert if we find */ \
2389 /* ourselves back in this routine later, */ \
2390 /* with the same di */ \
2391 di->soname = NULL; \
2392 goto out; \
2393 } while (0)
2395 /* Find avma-s for: .text .data .sdata .rodata .bss .sbss .plt .got .opd
2396 and .eh_frame */
2398 /* In inrw2 is non-NULL then it will be used for .data .got.plt .bss */
2400 /* Accept .text where mapped as rx (code), even if zero-sized */
2401 if (0 == VG_(strcmp)(name, ".text")) {
2402 if (inrx && !di->text_present) {
2403 di->text_present = True;
2404 di->text_svma = svma;
2405 di->text_avma = svma + inrx->bias;
2406 di->text_size = size;
2407 di->text_bias = inrx->bias;
2408 di->text_debug_svma = svma;
2409 di->text_debug_bias = inrx->bias;
2410 TRACE_SYMTAB("acquiring .text svma = %#lx .. %#lx\n",
2411 di->text_svma,
2412 di->text_svma + di->text_size - 1);
2413 TRACE_SYMTAB("acquiring .text avma = %#lx .. %#lx\n",
2414 di->text_avma,
2415 di->text_avma + di->text_size - 1);
2416 TRACE_SYMTAB("acquiring .text bias = %#lx\n", (UWord)di->text_bias);
2417 } else {
2418 BAD(".text");
2422 /* Accept .data where mapped as rw (data), even if zero-sized */
2423 if (0 == VG_(strcmp)(name, ".data")) {
2424 if (inrw2) {
2425 inrw = inrw2;
2426 } else {
2427 inrw = inrw1;
2430 # if defined(SOLARIS_PT_SUNDWTRACE_THRP)
2431 if ((size == VKI_PT_SUNWDTRACE_SIZE) && (svma == dtrace_data_vaddr)) {
2432 TRACE_SYMTAB("ignoring .data section for dtrace_data "
2433 "%#lx .. %#lx\n", svma, svma + size - 1);
2434 } else
2435 # endif /* SOLARIS_PT_SUNDWTRACE_THRP */
2437 if (inrw && !di->data_present) {
2438 di->data_present = True;
2439 di->data_svma = svma;
2440 di->data_avma = svma + inrw->bias;
2441 di->data_size = size;
2442 di->data_bias = inrw->bias;
2443 di->data_debug_svma = svma;
2444 di->data_debug_bias = inrw->bias;
2445 TRACE_SYMTAB("acquiring .data svma = %#lx .. %#lx\n",
2446 di->data_svma,
2447 di->data_svma + di->data_size - 1);
2448 TRACE_SYMTAB("acquiring .data avma = %#lx .. %#lx\n",
2449 di->data_avma,
2450 di->data_avma + di->data_size - 1);
2451 TRACE_SYMTAB("acquiring .data bias = %#lx\n", (UWord)di->data_bias);
2452 } else {
2453 BAD(".data");
2457 /* Accept .sdata where mapped as rw (data) */
2458 if (0 == VG_(strcmp)(name, ".sdata")) {
2459 if (inrw1 && !di->sdata_present) {
2460 di->sdata_present = True;
2461 di->sdata_svma = svma;
2462 di->sdata_avma = svma + inrw1->bias;
2463 di->sdata_size = size;
2464 di->sdata_bias = inrw1->bias;
2465 di->sdata_debug_svma = svma;
2466 di->sdata_debug_bias = inrw1->bias;
2467 TRACE_SYMTAB("acquiring .sdata svma = %#lx .. %#lx\n",
2468 di->sdata_svma,
2469 di->sdata_svma + di->sdata_size - 1);
2470 TRACE_SYMTAB("acquiring .sdata avma = %#lx .. %#lx\n",
2471 di->sdata_avma,
2472 di->sdata_avma + di->sdata_size - 1);
2473 TRACE_SYMTAB("acquiring .sdata bias = %#lx\n",
2474 (UWord)di->sdata_bias);
2475 } else {
2476 BAD(".sdata");
2480 /* Accept .rodata where mapped as rx or rw (data), even if zero-sized */
2481 /* Also accept .rodata.<subr_name>, and aggregate adjacent after alignment. */
2482 if (0 == VG_(strncmp)(name, ".rodata", 7)) {
2483 if ((inrx||inrw1) && !di->rodata_present) { /* first .rodata* */
2484 di->rodata_svma = svma;
2485 di->rodata_avma = svma;
2486 di->rodata_size = size;
2487 di->rodata_debug_svma = svma;
2488 } else if ((inrx||inrw1) && di->rodata_present) { /* not first .rodata* */
2489 Addr tmp = VG_ROUNDUP(di->rodata_size + di->rodata_svma, alyn);
2490 if (svma == tmp) { /* adjacent to previous .rodata* */
2491 di->rodata_size = size + tmp - di->rodata_svma;
2492 } else {
2493 /* is OK, but we cannot handle multiple .rodata* */
2494 TRACE_SYMTAB("%s section avma = %#lx .. %#lx is not contiguous, not merged\n",
2495 name,
2496 di->rodata_avma,
2497 di->rodata_avma + di->rodata_size - 1);
2498 goto out_rodata;
2501 if (inrx) {
2502 di->rodata_avma += inrx->bias;
2503 di->rodata_bias = inrx->bias;
2504 di->rodata_debug_bias = inrx->bias;
2505 } else if (inrw1) {
2506 di->rodata_avma += inrw1->bias;
2507 di->rodata_bias = inrw1->bias;
2508 di->rodata_debug_bias = inrw1->bias;
2509 } else {
2510 BAD(".rodata"); /* should not happen? */
2512 di->rodata_present = True;
2513 TRACE_SYMTAB("acquiring .rodata svma = %#lx .. %#lx\n",
2514 di->rodata_svma,
2515 di->rodata_svma + di->rodata_size - 1);
2516 TRACE_SYMTAB("acquiring .rodata avma = %#lx .. %#lx\n",
2517 di->rodata_avma,
2518 di->rodata_avma + di->rodata_size - 1);
2519 TRACE_SYMTAB("acquiring .rodata bias = %#lx\n",
2520 (UWord)di->rodata_bias);
2522 out_rodata:
2524 if (0 == VG_(strcmp)(name, ".dynbss")) {
2525 if (inrw1 && !di->bss_present) {
2526 dynbss_present = True;
2527 di->bss_present = True;
2528 di->bss_svma = svma;
2529 di->bss_avma = svma + inrw1->bias;
2530 di->bss_size = size;
2531 di->bss_bias = inrw1->bias;
2532 di->bss_debug_svma = svma;
2533 di->bss_debug_bias = inrw1->bias;
2534 TRACE_SYMTAB("acquiring .dynbss svma = %#lx .. %#lx\n",
2535 di->bss_svma,
2536 di->bss_svma + di->bss_size - 1);
2537 TRACE_SYMTAB("acquiring .dynbss avma = %#lx .. %#lx\n",
2538 di->bss_avma,
2539 di->bss_avma + di->bss_size - 1);
2540 TRACE_SYMTAB("acquiring .dynbss bias = %#lx\n",
2541 (UWord)di->bss_bias);
2545 /* Accept .bss where mapped as rw (data), even if zero-sized */
2546 if (0 == VG_(strcmp)(name, ".bss")) {
2548 if (inrw2) {
2549 inrw = inrw2;
2550 } else {
2551 inrw = inrw1;
2554 if (inrw && dynbss_present) {
2555 vg_assert(di->bss_present);
2556 dynbss_present = False;
2557 vg_assert(di->bss_svma + di->bss_size == svma);
2558 di->bss_size += size;
2559 TRACE_SYMTAB("acquiring .bss svma = %#lx .. %#lx\n",
2560 svma, svma + size - 1);
2561 TRACE_SYMTAB("acquiring .bss avma = %#lx .. %#lx\n",
2562 svma + inrw->bias, svma + inrw->bias + size - 1);
2563 TRACE_SYMTAB("acquiring .bss bias = %#lx\n",
2564 (UWord)di->bss_bias);
2565 } else
2567 if (inrw && !di->bss_present) {
2568 di->bss_present = True;
2569 di->bss_svma = svma;
2570 di->bss_avma = svma + inrw->bias;
2571 di->bss_size = size;
2572 di->bss_bias = inrw->bias;
2573 di->bss_debug_svma = svma;
2574 di->bss_debug_bias = inrw->bias;
2575 TRACE_SYMTAB("acquiring .bss svma = %#lx .. %#lx\n",
2576 di->bss_svma,
2577 di->bss_svma + di->bss_size - 1);
2578 TRACE_SYMTAB("acquiring .bss avma = %#lx .. %#lx\n",
2579 di->bss_avma,
2580 di->bss_avma + di->bss_size - 1);
2581 TRACE_SYMTAB("acquiring .bss bias = %#lx\n",
2582 (UWord)di->bss_bias);
2583 } else
2585 /* Now one from the wtf?! department ... */
2586 if (inrx && (!inrw) && !di->bss_present) {
2587 /* File contains a .bss, but it got mapped as rx only.
2588 This is very strange. For now, just pretend we didn't
2589 see it :-) */
2590 di->bss_present = False;
2591 di->bss_svma = 0;
2592 di->bss_avma = 0;
2593 di->bss_size = 0;
2594 di->bss_bias = 0;
2595 di->bss_debug_svma = 0;
2596 di->bss_debug_bias = 0;
2597 if (!VG_(clo_xml)) {
2598 VG_(message)(Vg_UserMsg,
2599 "Warning: the following file's .bss is "
2600 "mapped r-x only - ignoring .bss syms\n");
2601 VG_(message)(Vg_UserMsg, " %s\n", di->fsm.filename
2602 ? di->fsm.filename
2603 : "(null?!)" );
2605 } else
2607 if ((!inrw) && (!inrx) && !di->bss_present) {
2608 /* File contains a .bss, but it didn't get mapped. Ignore. */
2609 di->bss_present = False;
2610 di->bss_svma = 0;
2611 di->bss_avma = 0;
2612 di->bss_size = 0;
2613 di->bss_bias = 0;
2614 } else {
2615 BAD(".bss");
2619 if (0 == VG_(strcmp)(name, ".sdynbss")) {
2620 if (inrw1 && !di->sbss_present) {
2621 sdynbss_present = True;
2622 di->sbss_present = True;
2623 di->sbss_svma = svma;
2624 di->sbss_avma = svma + inrw1->bias;
2625 di->sbss_size = size;
2626 di->sbss_bias = inrw1->bias;
2627 di->sbss_debug_svma = svma;
2628 di->sbss_debug_bias = inrw1->bias;
2629 TRACE_SYMTAB("acquiring .sdynbss svma = %#lx .. %#lx\n",
2630 di->sbss_svma,
2631 di->sbss_svma + di->sbss_size - 1);
2632 TRACE_SYMTAB("acquiring .sdynbss avma = %#lx .. %#lx\n",
2633 di->sbss_avma,
2634 di->sbss_avma + di->sbss_size - 1);
2635 TRACE_SYMTAB("acquiring .sdynbss bias = %#lx\n",
2636 (UWord)di->sbss_bias);
2640 /* Accept .sbss where mapped as rw (data) */
2641 if (0 == VG_(strcmp)(name, ".sbss")) {
2642 if (inrw1 && sdynbss_present) {
2643 vg_assert(di->sbss_present);
2644 sdynbss_present = False;
2645 vg_assert(di->sbss_svma + di->sbss_size == svma);
2646 di->sbss_size += size;
2647 TRACE_SYMTAB("acquiring .sbss svma = %#lx .. %#lx\n",
2648 svma, svma + size - 1);
2649 TRACE_SYMTAB("acquiring .sbss avma = %#lx .. %#lx\n",
2650 svma + inrw1->bias, svma + inrw1->bias + size - 1);
2651 TRACE_SYMTAB("acquiring .sbss bias = %#lx\n", (UWord)di->sbss_bias);
2652 } else
2654 if (inrw1 && !di->sbss_present) {
2655 di->sbss_present = True;
2656 di->sbss_svma = svma;
2657 di->sbss_avma = svma + inrw1->bias;
2658 di->sbss_size = size;
2659 di->sbss_bias = inrw1->bias;
2660 di->sbss_debug_svma = svma;
2661 di->sbss_debug_bias = inrw1->bias;
2662 TRACE_SYMTAB("acquiring .sbss svma = %#lx .. %#lx\n",
2663 di->sbss_svma,
2664 di->sbss_svma + di->sbss_size - 1);
2665 TRACE_SYMTAB("acquiring .sbss avma = %#lx .. %#lx\n",
2666 di->sbss_avma,
2667 di->sbss_avma + di->sbss_size - 1);
2668 TRACE_SYMTAB("acquiring .sbss bias = %#lx\n", (UWord)di->sbss_bias);
2669 } else {
2670 BAD(".sbss");
2674 /* Accept .got where mapped as rw (data) */
2675 if (0 == VG_(strcmp)(name, ".got")) {
2676 if (inrw1 && !di->got_present) {
2677 di->got_present = True;
2678 di->got_avma = svma + inrw1->bias;
2679 di->got_size = size;
2680 TRACE_SYMTAB("acquiring .got avma = %#lx\n", di->got_avma);
2681 } else {
2682 BAD(".got");
2686 /* Accept .got.plt where mapped as rw (data) */
2687 if (0 == VG_(strcmp)(name, ".got.plt")) {
2689 if (inrw2) {
2690 inrw = inrw2;
2691 } else {
2692 inrw = inrw1;
2695 if (inrw && !di->gotplt_present) {
2696 di->gotplt_present = True;
2697 di->gotplt_avma = svma + inrw->bias;
2698 di->gotplt_size = size;
2699 TRACE_SYMTAB("acquiring .got.plt avma = %#lx\n", di->gotplt_avma);
2700 } else if (size != 0) {
2701 BAD(".got.plt");
2705 /* PLT is different on different platforms, it seems. */
2706 # if defined(VGP_x86_linux) || defined(VGP_amd64_linux) \
2707 || defined(VGP_arm_linux) || defined (VGP_s390x_linux) \
2708 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
2709 || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
2710 || defined(VGP_x86_solaris) || defined(VGP_amd64_solaris) \
2711 || defined(VGP_x86_freebsd) || defined(VGP_amd64_freebsd)
2712 /* Accept .plt where mapped as rx (code) */
2713 if (0 == VG_(strcmp)(name, ".plt")) {
2714 if (inrx && !di->plt_present) {
2715 di->plt_present = True;
2716 di->plt_avma = svma + inrx->bias;
2717 di->plt_size = size;
2718 TRACE_SYMTAB("acquiring .plt avma = %#lx\n", di->plt_avma);
2719 } else {
2720 BAD(".plt");
2723 # elif defined(VGP_ppc32_linux)
2724 /* Accept .plt where mapped as rw (data) */
2725 if (0 == VG_(strcmp)(name, ".plt")) {
2726 if (inrw1 && !di->plt_present) {
2727 di->plt_present = True;
2728 di->plt_avma = svma + inrw1->bias;
2729 di->plt_size = size;
2730 TRACE_SYMTAB("acquiring .plt avma = %#lx\n", di->plt_avma);
2731 } else {
2732 BAD(".plt");
2735 # elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
2736 /* Accept .plt where mapped as rw (data), or unmapped */
2737 if (0 == VG_(strcmp)(name, ".plt")) {
2738 if (inrw1 && !di->plt_present) {
2739 di->plt_present = True;
2740 di->plt_avma = svma + inrw1->bias;
2741 di->plt_size = size;
2742 TRACE_SYMTAB("acquiring .plt avma = %#lx\n", di->plt_avma);
2743 } else
2744 if ((!inrw1) && (!inrx) && size > 0 && !di->plt_present) {
2745 /* File contains a .plt, but it didn't get mapped.
2746 Presumably it is not required on this platform. At
2747 least don't reject the situation as invalid. */
2748 di->plt_present = True;
2749 di->plt_avma = 0;
2750 di->plt_size = 0;
2751 } else {
2752 BAD(".plt");
2755 # else
2756 # error "Unsupported platform"
2757 # endif
2759 /* Accept .opd where mapped as rw (data) */
2760 if (0 == VG_(strcmp)(name, ".opd")) {
2761 if (inrw1 && !di->opd_present) {
2762 di->opd_present = True;
2763 di->opd_avma = svma + inrw1->bias;
2764 di->opd_size = size;
2765 TRACE_SYMTAB("acquiring .opd avma = %#lx\n", di->opd_avma);
2766 } else {
2767 BAD(".opd");
2771 /* Accept .eh_frame where mapped as rx (code). This seems to be
2772 the common case. However, if that doesn't pan out, try for
2773 rw (data) instead. We can handle up to N_EHFRAME_SECTS per
2774 ELF object. */
2775 if (0 == VG_(strcmp)(name, ".eh_frame")) {
2776 if (inrx && di->n_ehframe < N_EHFRAME_SECTS) {
2777 di->ehframe_avma[di->n_ehframe] = svma + inrx->bias;
2778 di->ehframe_size[di->n_ehframe] = size;
2779 TRACE_SYMTAB("acquiring .eh_frame avma = %#lx\n",
2780 di->ehframe_avma[di->n_ehframe]);
2781 di->n_ehframe++;
2782 } else
2783 if (inrw1 && di->n_ehframe < N_EHFRAME_SECTS) {
2784 di->ehframe_avma[di->n_ehframe] = svma + inrw1->bias;
2785 di->ehframe_size[di->n_ehframe] = size;
2786 TRACE_SYMTAB("acquiring .eh_frame avma = %#lx\n",
2787 di->ehframe_avma[di->n_ehframe]);
2788 di->n_ehframe++;
2789 } else {
2790 BAD(".eh_frame");
2794 /* Accept .ARM.exidx where mapped as rx (code). */
2795 /* FIXME: make sure the entire section is mapped in, not just
2796 the first address. */
2797 if (0 == VG_(strcmp)(name, ".ARM.exidx")) {
2798 if (inrx && !di->exidx_present) {
2799 di->exidx_present = True;
2800 di->exidx_svma = svma;
2801 di->exidx_avma = svma + inrx->bias;
2802 di->exidx_size = size;
2803 di->exidx_bias = inrx->bias;
2804 TRACE_SYMTAB("acquiring .exidx svma = %#lx .. %#lx\n",
2805 di->exidx_svma,
2806 di->exidx_svma + di->exidx_size - 1);
2807 TRACE_SYMTAB("acquiring .exidx avma = %#lx .. %#lx\n",
2808 di->exidx_avma,
2809 di->exidx_avma + di->exidx_size - 1);
2810 TRACE_SYMTAB("acquiring .exidx bias = %#lx\n",
2811 (UWord)di->exidx_bias);
2812 } else {
2813 BAD(".ARM.exidx");
2817 /* Accept .ARM.extab where mapped as rx (code). */
2818 /* FIXME: make sure the entire section is mapped in, not just
2819 the first address. */
2820 if (0 == VG_(strcmp)(name, ".ARM.extab")) {
2821 if (inrx && !di->extab_present) {
2822 di->extab_present = True;
2823 di->extab_svma = svma;
2824 di->extab_avma = svma + inrx->bias;
2825 di->extab_size = size;
2826 di->extab_bias = inrx->bias;
2827 TRACE_SYMTAB("acquiring .extab svma = %#lx .. %#lx\n",
2828 di->extab_svma,
2829 di->extab_svma + di->extab_size - 1);
2830 TRACE_SYMTAB("acquiring .extab avma = %#lx .. %#lx\n",
2831 di->extab_avma,
2832 di->extab_avma + di->extab_size - 1);
2833 TRACE_SYMTAB("acquiring .extab bias = %#lx\n",
2834 (UWord)di->extab_bias);
2835 } else {
2836 BAD(".ARM.extab");
2840 ML_(dinfo_free)(name);
2842 # undef BAD
2844 } /* iterate over the section headers */
2846 /* TOPLEVEL */
2847 if (0) VG_(printf)("YYYY text_: avma %#lx size %lu bias %#lx\n",
2848 di->text_avma, di->text_size, (UWord)di->text_bias);
2850 if (VG_(clo_verbosity) > 2 || VG_(clo_trace_redir))
2851 VG_(message)(Vg_DebugMsg, " svma %#010lx, avma %#010lx\n",
2852 di->text_avma - di->text_bias,
2853 di->text_avma );
2855 /* TOPLEVEL */
2856 /* Find interesting sections, read the symbol table(s), read any
2857 debug information. Each section is located either in the main,
2858 debug or alt-debug files, but only in one. For each section,
2859 |section_escn| records which of |mimg|, |dimg| or |aimg| we
2860 found it in, along with the section's image offset and its size.
2861 The triples (section_img, section_ioff, section_szB) are
2862 consistent, in that they are always either (NULL,
2863 DiOffT_INVALID, 0), or refer to the same image, and are all
2864 assigned together. */
2866 /* TOPLEVEL */
2867 DiSlice strtab_escn = DiSlice_INVALID; // .strtab
2868 DiSlice symtab_escn = DiSlice_INVALID; // .symtab
2869 DiSlice dynstr_escn = DiSlice_INVALID; // .dynstr
2870 DiSlice dynsym_escn = DiSlice_INVALID; // .dynsym
2871 # if defined(VGO_solaris)
2872 DiSlice ldynsym_escn = DiSlice_INVALID; // .SUNW_ldynsym
2873 # endif
2874 DiSlice opd_escn = DiSlice_INVALID; // .opd (dwarf2,
2875 // ppc64be-linux)
2876 DiSlice ehframe_escn[N_EHFRAME_SECTS]; // .eh_frame (dwarf2)
2878 for (i = 0; i < N_EHFRAME_SECTS; i++)
2879 ehframe_escn[i] = DiSlice_INVALID;
2881 /* Find all interesting sections */
2883 UInt ehframe_mix = 0;
2885 /* What FIND does: it finds the section called _SEC_NAME. The
2886 size of it is assigned to _SEC_SIZE. The address of the
2887 section in the transiently loaded oimage is assigned to
2888 _SEC_IMG. If the section is found, _POST_FX is executed
2889 after _SEC_NAME and _SEC_SIZE have been assigned to.
2891 Even for sections which are marked loadable, the client's
2892 ld.so may not have loaded them yet, so there is no guarantee
2893 that we can safely prod around in any such area). Because
2894 the entire object file is transiently mapped aboard for
2895 inspection, it's always safe to inspect that area. */
2897 /* TOPLEVEL */
2898 /* Iterate over section headers (again) */
2899 for (i = 0; i < ehdr_m.e_shnum; i++) {
2900 /* NAME ElfSec */
2901 FIND_MIMG( ".dynsym", dynsym_escn)
2902 FIND_MIMG( ".dynstr", dynstr_escn)
2903 FIND_MIMG( ".symtab", symtab_escn)
2904 FIND_MIMG( ".strtab", strtab_escn)
2905 # if defined(VGO_solaris)
2906 FIND_MIMG( ".SUNW_ldynsym", ldynsym_escn)
2907 # endif
2908 FIND_MIMG( ".opd", opd_escn)
2910 FINDX_MIMG( ".eh_frame", ehframe_escn[ehframe_mix],
2911 do { ehframe_mix++; vg_assert(ehframe_mix <= N_EHFRAME_SECTS);
2912 } while (0)
2914 /* Comment_on_EH_FRAME_MULTIPLE_INSTANCES: w.r.t. .eh_frame
2915 multi-instance kludgery, how are we assured that the order
2916 in which we fill in ehframe_escn[] is consistent with the
2917 order in which we previously filled in di->ehframe_avma[]
2918 and di->ehframe_size[] ? By the fact that in both cases,
2919 these arrays were filled in by iterating over the section
2920 headers top-to-bottom. So both loops (this one and the
2921 previous one) encounter the .eh_frame entries in the same
2922 order and so fill in these arrays in a consistent order.
2924 } /* Iterate over section headers (again) */
2926 /* Check some sizes */
2927 vg_assert((dynsym_escn.szB % sizeof(ElfXX_Sym)) == 0);
2928 vg_assert((symtab_escn.szB % sizeof(ElfXX_Sym)) == 0);
2929 # if defined(VGO_solaris)
2930 vg_assert((ldynsym_escn.szB % sizeof(ElfXX_Sym)) == 0);
2931 # endif
2933 /* Read symbols */
2935 void (*read_elf_symtab)(struct _DebugInfo*, const HChar*,
2936 DiSlice*, DiSlice*, DiSlice*, Bool);
2937 # if defined(VGP_ppc64be_linux)
2938 read_elf_symtab = read_elf_symtab__ppc64be_linux;
2939 # else
2940 read_elf_symtab = read_elf_symtab__normal;
2941 # endif
2942 if (symtab_escn.img != NULL)
2943 read_elf_symtab(di, "symbol table",
2944 &symtab_escn, &strtab_escn, &opd_escn,
2945 False);
2946 read_elf_symtab(di, "dynamic symbol table",
2947 &dynsym_escn, &dynstr_escn, &opd_escn,
2948 False);
2949 # if defined(VGO_solaris)
2950 read_elf_symtab(di, "local dynamic symbol table",
2951 &ldynsym_escn, &dynstr_escn, &opd_escn,
2952 False);
2953 # endif
2956 /* TOPLEVEL */
2957 /* Read .eh_frame and .debug_frame (call-frame-info) if any. Do
2958 the .eh_frame section(s) first. */
2959 /* i->n_ehframe is unsigned and cannot be negative */
2960 vg_assert(di->n_ehframe <= N_EHFRAME_SECTS);
2961 for (i = 0; i < di->n_ehframe; i++) {
2962 /* see Comment_on_EH_FRAME_MULTIPLE_INSTANCES above for why
2963 this next assertion should hold. */
2964 vg_assert(ML_(sli_is_valid)(ehframe_escn[i]));
2965 vg_assert(ehframe_escn[i].szB == di->ehframe_size[i]);
2966 ML_(read_callframe_info_dwarf3)( di,
2967 ehframe_escn[i],
2968 di->ehframe_avma[i],
2969 True/*is_ehframe*/ );
2973 retval = True;
2975 out:
2977 /* Last, but not least, detach from the image. */
2978 if (mimg) ML_(img_done)(mimg);
2980 if (svma_ranges) VG_(deleteXA)(svma_ranges);
2982 return retval;
2985 static void find_rodata(Word i, Word shnum, DiImage* dimg, struct _DebugInfo* di, DiOffT shdr_dioff,
2986 UWord shdr_dent_szB, DiOffT shdr_strtab_dioff, PtrdiffT rw_dbias)
2988 ElfXX_Shdr a_shdr;
2989 ElfXX_Shdr a_extra_shdr;
2990 ML_(img_get)(&a_shdr, dimg,
2991 INDEX_BIS(shdr_dioff, i, shdr_dent_szB),
2992 sizeof(a_shdr));
2993 if (di->rodata_present &&
2994 0 == ML_(img_strcmp_c)(dimg, shdr_strtab_dioff
2995 + a_shdr.sh_name, ".rodata")) {
2996 Word sh_size = a_shdr.sh_size;
2997 Word j;
2998 Word next_addr = a_shdr.sh_addr + a_shdr.sh_size;
2999 for (j = i + 1; j < shnum; ++j) {
3000 ML_(img_get)(&a_extra_shdr, dimg,
3001 INDEX_BIS(shdr_dioff, j, shdr_dent_szB),
3002 sizeof(a_shdr));
3003 if (0 == ML_(img_strcmp_n)(dimg, shdr_strtab_dioff
3004 + a_extra_shdr.sh_name, ".rodata", 7)) {
3005 if (a_extra_shdr.sh_addr ==
3006 VG_ROUNDUP(next_addr, a_extra_shdr.sh_addralign)) {
3007 sh_size = VG_ROUNDUP(sh_size, a_extra_shdr.sh_addralign) + a_extra_shdr.sh_size;
3009 next_addr = a_extra_shdr.sh_addr + a_extra_shdr.sh_size;
3010 } else {
3011 break;
3014 vg_assert(di->rodata_size == sh_size);
3015 vg_assert(di->rodata_avma + a_shdr.sh_addr + rw_dbias);
3016 di->rodata_debug_svma = a_shdr.sh_addr;
3017 di->rodata_debug_bias = di->rodata_bias +
3018 di->rodata_svma - di->rodata_debug_svma;
3019 TRACE_SYMTAB("acquiring .rodata debug svma = %#lx .. %#lx\n",
3020 di->rodata_debug_svma,
3021 di->rodata_debug_svma + di->rodata_size - 1);
3022 TRACE_SYMTAB("acquiring .rodata debug bias = %#lx\n", (UWord)di->rodata_debug_bias);
3025 Bool ML_(read_elf_debug) ( struct _DebugInfo* di )
3027 Word i, j;
3028 Bool res = True;
3029 Bool ok;
3031 /* Image for the main ELF file we're working with. */
3032 DiImage* mimg = NULL;
3034 /* Ditto for any ELF debuginfo file that we might happen to load. */
3035 DiImage* dimg = NULL;
3037 /* Ditto for alternate ELF debuginfo file that we might happen to load. */
3038 DiImage* aimg = NULL;
3040 /* Section header image addr, # entries, entry size. Also the
3041 associated string table. */
3042 DiOffT shdr_mioff = 0;
3043 UWord shdr_mnent = 0;
3044 UWord shdr_ment_szB = 0;
3045 DiOffT shdr_strtab_mioff = 0;
3047 DiOffT ehdr_mioff = 0;
3049 /* Connect to the primary object image, so that we can read symbols
3050 and line number info out of it. It will be disconnected
3051 immediately thereafter; it is only connected transiently. */
3052 mimg = ML_(img_from_local_file)(di->fsm.filename);
3053 if (mimg == NULL) {
3054 VG_(message)(Vg_UserMsg, "warning: connection to image %s failed\n",
3055 di->fsm.filename );
3056 VG_(message)(Vg_UserMsg, " no debug info loaded\n" );
3057 return False;
3060 /* Ok, the object image is available. Now verify that it is a
3061 valid ELF .so or executable image. */
3062 ok = is_elf_object_file_by_DiImage(mimg, False);
3063 if (!ok) {
3064 ML_(symerr)(di, True, "Invalid ELF Header");
3065 goto out;
3068 /* Find where the program and section header tables are, and give
3069 up if either is missing or outside the image (bogus). */
3070 ElfXX_Ehdr ehdr_m;
3071 vg_assert(ehdr_mioff == 0); // ensured by its initialisation
3072 ok = ML_(img_valid)(mimg, ehdr_mioff, sizeof(ehdr_m));
3073 vg_assert(ok); // ML_(is_elf_object_file) should ensure this
3074 ML_(img_get)(&ehdr_m, mimg, ehdr_mioff, sizeof(ehdr_m));
3076 shdr_mioff = ehdr_mioff + ehdr_m.e_shoff;
3077 shdr_mnent = ehdr_m.e_shnum;
3078 shdr_ment_szB = ehdr_m.e_shentsize;
3080 if (shdr_mnent == 0
3081 || !ML_(img_valid)(mimg, shdr_mioff, shdr_mnent * shdr_ment_szB)) {
3082 ML_(symerr)(di, True, "Missing or invalid ELF Section Header Table");
3083 goto out;
3086 /* Also find the section header's string table, and validate. */
3087 /* checked previously by is_elf_object_file: */
3088 vg_assert(ehdr_m.e_shstrndx != SHN_UNDEF);
3090 // shdr_mioff is the offset of the section header table
3091 // and we need the ehdr_m.e_shstrndx'th entry
3092 { ElfXX_Shdr a_shdr;
3093 ML_(img_get)(&a_shdr, mimg,
3094 INDEX_BIS(shdr_mioff, ehdr_m.e_shstrndx, shdr_ment_szB),
3095 sizeof(a_shdr));
3096 shdr_strtab_mioff
3097 = ehdr_mioff /* isn't this always zero? */ + a_shdr.sh_offset;
3099 if (!ML_(img_valid)(mimg, shdr_strtab_mioff,
3100 1/*bogus, but we don't know the real size*/ )) {
3101 ML_(symerr)(di, True, "Invalid ELF Section Header String Table");
3102 goto out;
3106 TRACE_SYMTAB("\n");
3107 TRACE_SYMTAB("------ Finding image addresses "
3108 "for debug-info sections ------\n");
3109 /* TOPLEVEL */
3110 /* Find interesting sections, read the symbol table(s), read any
3111 debug information. Each section is located either in the main,
3112 debug or alt-debug files, but only in one. For each section,
3113 |section_escn| records which of |mimg|, |dimg| or |aimg| we
3114 found it in, along with the section's image offset and its size.
3115 The triples (section_img, section_ioff, section_szB) are
3116 consistent, in that they are always either (NULL,
3117 DiOffT_INVALID, 0), or refer to the same image, and are all
3118 assigned together. */
3121 /* TOPLEVEL */
3122 DiSlice strtab_escn = DiSlice_INVALID; // .strtab
3123 DiSlice symtab_escn = DiSlice_INVALID; // .symtab
3124 DiSlice debuglink_escn = DiSlice_INVALID; // .gnu_debuglink
3125 DiSlice debugaltlink_escn = DiSlice_INVALID; // .gnu_debugaltlink
3126 DiSlice debug_line_escn = DiSlice_INVALID; // .debug_line (dwarf2)
3127 DiSlice debug_info_escn = DiSlice_INVALID; // .debug_info (dwarf2)
3128 DiSlice debug_types_escn = DiSlice_INVALID; // .debug_types (dwarf4)
3129 DiSlice debug_abbv_escn = DiSlice_INVALID; // .debug_abbrev (dwarf2)
3130 DiSlice debug_str_escn = DiSlice_INVALID; // .debug_str (dwarf2)
3131 DiSlice debug_line_str_escn = DiSlice_INVALID; // .debug_line_str(dwarf5)
3132 DiSlice debug_ranges_escn = DiSlice_INVALID; // .debug_ranges (dwarf2)
3133 DiSlice debug_rnglists_escn = DiSlice_INVALID; // .debug_rnglists(dwarf5)
3134 DiSlice debug_loclists_escn = DiSlice_INVALID; // .debug_loclists(dwarf5)
3135 DiSlice debug_addr_escn = DiSlice_INVALID; // .debug_addr (dwarf5)
3136 DiSlice debug_str_offsets_escn = DiSlice_INVALID; // .debug_str_offsets (dwarf5)
3137 DiSlice debug_loc_escn = DiSlice_INVALID; // .debug_loc (dwarf2)
3138 DiSlice debug_frame_escn = DiSlice_INVALID; // .debug_frame (dwarf2)
3139 DiSlice debug_line_alt_escn = DiSlice_INVALID; // .debug_line (alt)
3140 DiSlice debug_info_alt_escn = DiSlice_INVALID; // .debug_info (alt)
3141 DiSlice debug_abbv_alt_escn = DiSlice_INVALID; // .debug_abbrev (alt)
3142 DiSlice debug_str_alt_escn = DiSlice_INVALID; // .debug_str (alt)
3143 DiSlice dwarf1d_escn = DiSlice_INVALID; // .debug (dwarf1)
3144 DiSlice dwarf1l_escn = DiSlice_INVALID; // .line (dwarf1)
3145 DiSlice opd_escn = DiSlice_INVALID; // .opd (dwarf2,
3146 // ppc64be-linux)
3148 /* TOPLEVEL */
3149 /* Iterate over section headers (again) */
3150 for (i = 0; i < ehdr_m.e_shnum; i++) {
3152 /* NAME ElfSec */
3153 FIND_MIMG( ".symtab", symtab_escn)
3154 FIND_MIMG( ".strtab", strtab_escn)
3155 FIND_MIMG( ".gnu_debuglink", debuglink_escn)
3156 FIND_MIMG( ".gnu_debugaltlink", debugaltlink_escn)
3158 FIND_MIMG( ".debug_line", debug_line_escn)
3159 if (!ML_(sli_is_valid)(debug_line_escn))
3160 FIND_MIMG(".zdebug_line", debug_line_escn)
3162 FIND_MIMG( ".debug_info", debug_info_escn)
3163 if (!ML_(sli_is_valid)(debug_info_escn))
3164 FIND_MIMG(".zdebug_info", debug_info_escn)
3166 FIND_MIMG( ".debug_types", debug_types_escn)
3167 if (!ML_(sli_is_valid)(debug_types_escn))
3168 FIND_MIMG(".zdebug_types", debug_types_escn)
3170 FIND_MIMG( ".debug_abbrev", debug_abbv_escn)
3171 if (!ML_(sli_is_valid)(debug_abbv_escn))
3172 FIND_MIMG(".zdebug_abbrev", debug_abbv_escn)
3174 FIND_MIMG( ".debug_str", debug_str_escn)
3175 if (!ML_(sli_is_valid)(debug_str_escn))
3176 FIND_MIMG(".zdebug_str", debug_str_escn)
3178 FIND_MIMG( ".debug_line_str", debug_line_str_escn)
3179 if (!ML_(sli_is_valid)(debug_line_str_escn))
3180 FIND_MIMG(".zdebug_str", debug_line_str_escn)
3182 FIND_MIMG( ".debug_ranges", debug_ranges_escn)
3183 if (!ML_(sli_is_valid)(debug_ranges_escn))
3184 FIND_MIMG(".zdebug_ranges", debug_ranges_escn)
3186 FIND_MIMG( ".debug_rnglists", debug_rnglists_escn)
3187 if (!ML_(sli_is_valid)(debug_rnglists_escn))
3188 FIND_MIMG(".zdebug_rnglists", debug_rnglists_escn)
3190 FIND_MIMG( ".debug_loclists", debug_loclists_escn)
3191 if (!ML_(sli_is_valid)(debug_loclists_escn))
3192 FIND_MIMG(".zdebug_loclists", debug_loclists_escn)
3194 FIND_MIMG( ".debug_loc", debug_loc_escn)
3195 if (!ML_(sli_is_valid)(debug_loc_escn))
3196 FIND_MIMG(".zdebug_loc", debug_loc_escn)
3198 FIND_MIMG( ".debug_frame", debug_frame_escn)
3199 if (!ML_(sli_is_valid)(debug_frame_escn))
3200 FIND_MIMG(".zdebug_frame", debug_frame_escn)
3202 FIND_MIMG( ".debug_addr", debug_addr_escn)
3203 if (!ML_(sli_is_valid)(debug_addr_escn))
3204 FIND_MIMG(".zdebug_addr", debug_addr_escn)
3206 FIND_MIMG( ".debug_str_offsets", debug_str_offsets_escn)
3207 if (!ML_(sli_is_valid)(debug_str_offsets_escn))
3208 FIND_MIMG(".zdebug_str_offsets", debug_str_offsets_escn)
3210 FIND_MIMG( ".debug", dwarf1d_escn)
3211 FIND_MIMG( ".line", dwarf1l_escn)
3213 FIND_MIMG( ".opd", opd_escn)
3215 /* Comment_on_EH_FRAME_MULTIPLE_INSTANCES: w.r.t. .eh_frame
3216 multi-instance kludgery, how are we assured that the order
3217 in which we fill in ehframe_escn[] is consistent with the
3218 order in which we previously filled in di->ehframe_avma[]
3219 and di->ehframe_size[] ? By the fact that in both cases,
3220 these arrays were filled in by iterating over the section
3221 headers top-to-bottom. So both loops (this one and the
3222 previous one) encounter the .eh_frame entries in the same
3223 order and so fill in these arrays in a consistent order.
3226 } /* Iterate over section headers (again) */
3228 /* TOPLEVEL */
3229 /* Now, see if we can find a debuginfo object, and if so connect
3230 |dimg| to it. */
3231 vg_assert(dimg == NULL && aimg == NULL);
3233 #if defined(VGO_freebsd)
3234 /* */
3235 read_and_set_osrel(mimg);
3237 #endif
3239 /* Look for a build-id */
3240 HChar* buildid = find_buildid(mimg, False, False);
3242 /* If we don't have a .debug_info section in the main image then
3243 look for a debug image that matches either the build-id or
3244 the debuglink-CRC32 in the main image. If the main image
3245 doesn't contain either of those then this won't even bother
3246 to try looking. This looks in all known places, including
3247 the --extra-debuginfo-path if specified and on the
3248 --debuginfo-server if specified. */
3249 if (debug_info_escn.img == NULL &&
3250 (buildid != NULL || debuglink_escn.img != NULL)) {
3251 /* Do have a debuglink section? */
3252 if (debuglink_escn.img != NULL) {
3253 UInt crc_offset
3254 = VG_ROUNDUP(ML_(img_strlen)(debuglink_escn.img,
3255 debuglink_escn.ioff)+1, 4);
3256 vg_assert(crc_offset + sizeof(UInt) <= debuglink_escn.szB);
3258 /* Extract the CRC from the debuglink section */
3259 UInt crc = ML_(img_get_UInt)(debuglink_escn.img,
3260 debuglink_escn.ioff + crc_offset);
3262 /* See if we can find a matching debug file */
3263 HChar* debuglink_str_m
3264 = ML_(img_strdup)(debuglink_escn.img,
3265 "di.redi_dlk.1", debuglink_escn.ioff);
3266 dimg = find_debug_file( di, di->fsm.filename, buildid,
3267 debuglink_str_m, crc, False );
3268 if (debuglink_str_m)
3269 ML_(dinfo_free)(debuglink_str_m);
3270 } else {
3271 /* See if we can find a matching debug file */
3272 dimg = find_debug_file( di, di->fsm.filename, buildid,
3273 NULL, 0, False );
3277 if (buildid) {
3278 ML_(dinfo_free)(buildid);
3279 buildid = NULL; /* paranoia */
3282 /* As a last-ditch measure, try looking for in the
3283 --extra-debuginfo-path and/or on the --debuginfo-server, but
3284 only in the case where --allow-mismatched-debuginfo=yes.
3285 This is dangerous in that (1) it gives no assurance that the
3286 debuginfo object matches the main one, and hence (2) we will
3287 very likely get an assertion in the code below, if indeed
3288 there is a mismatch. Hence it is disabled by default
3289 (--allow-mismatched-debuginfo=no). Nevertheless it's
3290 sometimes a useful way of getting out of a tight spot.
3292 Note that we're ignoring the name in the .gnu_debuglink
3293 section here, and just looking for a file of the same name
3294 either the extra-path or on the server. */
3295 if (dimg == NULL && VG_(clo_allow_mismatched_debuginfo)) {
3296 dimg = find_debug_file_ad_hoc( di, di->fsm.filename );
3299 /* TOPLEVEL */
3300 /* If we were successful in finding a debug image, pull various
3301 SVMA/bias/size and image addresses out of it. */
3302 if (dimg != NULL && is_elf_object_file_by_DiImage(dimg, False)) {
3304 /* Pull out and validate program header and section header info */
3305 DiOffT ehdr_dioff = 0;
3306 ElfXX_Ehdr ehdr_dimg;
3307 ML_(img_get)(&ehdr_dimg, dimg, ehdr_dioff, sizeof(ehdr_dimg));
3309 DiOffT phdr_dioff = ehdr_dimg.e_phoff;
3310 UWord phdr_dnent = ehdr_dimg.e_phnum;
3311 UWord phdr_dent_szB = ehdr_dimg.e_phentsize;
3313 DiOffT shdr_dioff = ehdr_dimg.e_shoff;
3314 UWord shdr_dnent = ehdr_dimg.e_shnum;
3315 UWord shdr_dent_szB = ehdr_dimg.e_shentsize;
3317 DiOffT shdr_strtab_dioff = DiOffT_INVALID;
3319 /* SVMAs covered by rx and rw segments and corresponding bias. */
3320 Addr rx_dsvma_limit = 0;
3321 PtrdiffT rx_dbias = 0;
3322 Addr rw_dsvma_limit = 0;
3323 PtrdiffT rw_dbias = 0;
3325 Bool need_symtab, need_dwarf2, need_dwarf1;
3327 if (phdr_dnent == 0
3328 || !ML_(img_valid)(dimg, phdr_dioff,
3329 phdr_dnent * phdr_dent_szB)) {
3330 ML_(symerr)(di, True,
3331 "Missing or invalid ELF Program Header Table"
3332 " (debuginfo file)");
3333 goto out;
3336 if (shdr_dnent == 0
3337 || !ML_(img_valid)(dimg, shdr_dioff,
3338 shdr_dnent * shdr_dent_szB)) {
3339 ML_(symerr)(di, True,
3340 "Missing or invalid ELF Section Header Table"
3341 " (debuginfo file)");
3342 goto out;
3345 /* Also find the section header's string table, and validate. */
3346 /* checked previously by is_elf_object_file: */
3347 vg_assert(ehdr_dimg.e_shstrndx != SHN_UNDEF);
3349 // shdr_dioff is the offset of the section header table
3350 // and we need the ehdr_dimg.e_shstrndx'th entry
3351 { ElfXX_Shdr a_shdr;
3352 ML_(img_get)(&a_shdr, dimg,
3353 INDEX_BIS(shdr_dioff, ehdr_dimg.e_shstrndx,
3354 shdr_dent_szB),
3355 sizeof(a_shdr));
3356 shdr_strtab_dioff = a_shdr.sh_offset;
3357 if (!ML_(img_valid)(dimg, shdr_strtab_dioff,
3358 1/*bogus, but we don't know the real size*/)) {
3359 ML_(symerr)(di, True,
3360 "Invalid ELF Section Header String Table"
3361 " (debuginfo file)");
3362 goto out;
3366 for (i = 0; i < ehdr_dimg.e_phnum; i++) {
3367 ElfXX_Phdr a_phdr;
3368 ML_(img_get)(&a_phdr, dimg, INDEX_BIS(ehdr_dimg.e_phoff,
3369 i, phdr_dent_szB),
3370 sizeof(a_phdr));
3371 if (a_phdr.p_type == PT_LOAD) {
3372 for (j = 0; j < VG_(sizeXA)(di->fsm.maps); j++) {
3373 const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, j);
3374 if ( a_phdr.p_offset >= map->foff
3375 && a_phdr.p_offset < map->foff + map->size
3376 && a_phdr.p_offset + a_phdr.p_filesz
3377 < map->foff + map->size) {
3378 if (map->rx && rx_dsvma_limit == 0) {
3379 rx_dsvma_limit = a_phdr.p_vaddr + a_phdr.p_memsz;
3380 rx_dbias = map->avma - map->foff + a_phdr.p_offset
3381 - a_phdr.p_vaddr;
3383 if (map->rw && rw_dsvma_limit == 0) {
3384 rw_dsvma_limit = a_phdr.p_vaddr + a_phdr.p_memsz;
3385 rw_dbias = map->avma - map->foff + a_phdr.p_offset
3386 - a_phdr.p_vaddr;
3388 break;
3394 need_symtab = (symtab_escn.img == NULL);
3395 need_dwarf2 = (debug_info_escn.img == NULL);
3396 need_dwarf1 = (dwarf1d_escn.img == NULL);
3398 /* Find all interesting sections in the debug image */
3399 for (i = 0; i < ehdr_dimg.e_shnum; i++) {
3401 /* Find debug svma and bias information for sections
3402 we found in the main file. */
3404 # define FIND(_sec, _seg) \
3405 do { \
3406 ElfXX_Shdr a_shdr; \
3407 ML_(img_get)(&a_shdr, dimg, \
3408 INDEX_BIS(shdr_dioff, i, shdr_dent_szB), \
3409 sizeof(a_shdr)); \
3410 if (di->_sec##_present \
3411 && 0 == ML_(img_strcmp_c)(dimg, shdr_strtab_dioff \
3412 + a_shdr.sh_name, "." #_sec)) { \
3413 vg_assert(di->_sec##_size == a_shdr.sh_size); \
3414 /* JRS 2013-Jun-01: the following assert doesn't contain */ \
3415 /* any ==s, which seems to me to be suspicious. */ \
3416 vg_assert(di->_sec##_avma + a_shdr.sh_addr + _seg##_dbias); \
3417 /* Assume we have a correct value for the main */ \
3418 /* object's bias. Use that to derive the debuginfo */ \
3419 /* object's bias, by adding the difference in SVMAs */ \
3420 /* for the corresponding sections in the two files. */ \
3421 /* That should take care of all prelinking effects. */ \
3422 di->_sec##_debug_svma = a_shdr.sh_addr; \
3423 di->_sec##_debug_bias \
3424 = di->_sec##_bias + \
3425 di->_sec##_svma - di->_sec##_debug_svma; \
3426 TRACE_SYMTAB("acquiring ." #_sec \
3427 " debug svma = %#lx .. %#lx\n", \
3428 di->_sec##_debug_svma, \
3429 di->_sec##_debug_svma + di->_sec##_size - 1); \
3430 TRACE_SYMTAB("acquiring ." #_sec " debug bias = %#lx\n", \
3431 (UWord)di->_sec##_debug_bias); \
3433 } while (0);
3435 /* SECTION SEGMENT */
3436 FIND(text, rx)
3437 FIND(data, rw)
3438 FIND(sdata, rw)
3439 // https://bugs.kde.org/show_bug.cgi?id=476548
3440 // special handling for rodata as adjacent
3441 // rodata sections may have been merged in ML_(read_elf_object)
3442 //FIND(rodata, rw)
3443 find_rodata(i, ehdr_dimg.e_shnum, dimg, di, shdr_dioff, shdr_dent_szB, shdr_strtab_dioff, rw_dbias);
3444 FIND(bss, rw)
3445 FIND(sbss, rw)
3447 # undef FIND
3449 /* Same deal as previous FIND, except only do it for those
3450 sections which we didn't find in the main file. */
3452 # define FIND(_condition, _sec_name, _sec_escn) \
3453 do { \
3454 ElfXX_Shdr a_shdr; \
3455 ML_(img_get)(&a_shdr, dimg, \
3456 INDEX_BIS(shdr_dioff, i, shdr_dent_szB), \
3457 sizeof(a_shdr)); \
3458 if (_condition \
3459 && 0 == ML_(img_strcmp_c)(dimg, shdr_strtab_dioff \
3460 + a_shdr.sh_name, _sec_name)) { \
3461 Bool nobits; \
3462 if (_sec_escn.img != NULL) { \
3463 ML_(symerr)(di, True, \
3464 " debuginfo section duplicates a" \
3465 " section in the main ELF file"); \
3466 goto out; \
3468 _sec_escn.img = dimg; \
3469 _sec_escn.ioff = (DiOffT)a_shdr.sh_offset; \
3470 _sec_escn.szB = a_shdr.sh_size; \
3471 if (!check_compression(&a_shdr, &_sec_escn)) { \
3472 ML_(symerr)(di, True, " Compression type is unsupported"); \
3473 goto out; \
3475 nobits = a_shdr.sh_type == SHT_NOBITS; \
3476 vg_assert(_sec_escn.img != NULL); \
3477 vg_assert(_sec_escn.ioff != DiOffT_INVALID); \
3478 TRACE_SYMTAB( "%-18s: dioff %llu .. %llu\n", \
3479 _sec_name, \
3480 (ULong)a_shdr.sh_offset, \
3481 ((ULong)a_shdr.sh_offset) + a_shdr.sh_size - 1); \
3482 /* SHT_NOBITS sections have zero size in the file. */ \
3483 if (!nobits && a_shdr.sh_offset \
3484 + a_shdr.sh_size > ML_(img_real_size)(_sec_escn.img)) { \
3485 ML_(symerr)(di, True, \
3486 " section beyond image end?!"); \
3487 goto out; \
3490 } while (0);
3492 /* NEEDED? NAME ElfSec */
3493 FIND( need_symtab, ".symtab", symtab_escn)
3494 FIND( need_symtab, ".strtab", strtab_escn)
3495 FIND( need_dwarf2, ".debug_line", debug_line_escn)
3496 if (!ML_(sli_is_valid)(debug_line_escn))
3497 FIND(need_dwarf2, ".zdebug_line", debug_line_escn)
3499 FIND( need_dwarf2, ".debug_info", debug_info_escn)
3500 if (!ML_(sli_is_valid)(debug_info_escn))
3501 FIND(need_dwarf2, ".zdebug_info", debug_info_escn)
3503 FIND( need_dwarf2, ".debug_types", debug_types_escn)
3504 if (!ML_(sli_is_valid)(debug_types_escn))
3505 FIND(need_dwarf2, ".zdebug_types", debug_types_escn)
3507 FIND( need_dwarf2, ".debug_abbrev", debug_abbv_escn)
3508 if (!ML_(sli_is_valid)(debug_abbv_escn))
3509 FIND(need_dwarf2, ".zdebug_abbrev", debug_abbv_escn)
3511 FIND( need_dwarf2, ".debug_str", debug_str_escn)
3512 if (!ML_(sli_is_valid)(debug_str_escn))
3513 FIND(need_dwarf2, ".zdebug_str", debug_str_escn)
3515 FIND( need_dwarf2, ".debug_line_str", debug_line_str_escn)
3516 if (!ML_(sli_is_valid)(debug_line_str_escn))
3517 FIND(need_dwarf2, ".zdebug_line_str", debug_line_str_escn)
3519 FIND( need_dwarf2, ".debug_ranges", debug_ranges_escn)
3520 if (!ML_(sli_is_valid)(debug_ranges_escn))
3521 FIND(need_dwarf2, ".zdebug_ranges", debug_ranges_escn)
3523 FIND( need_dwarf2, ".debug_rnglists", debug_rnglists_escn)
3524 if (!ML_(sli_is_valid)(debug_rnglists_escn))
3525 FIND(need_dwarf2, ".zdebug_rnglists", debug_rnglists_escn)
3527 FIND( need_dwarf2, ".debug_loclists", debug_loclists_escn)
3528 if (!ML_(sli_is_valid)(debug_loclists_escn))
3529 FIND(need_dwarf2, ".zdebug_loclists", debug_loclists_escn)
3531 FIND( need_dwarf2, ".debug_loc", debug_loc_escn)
3532 if (!ML_(sli_is_valid)(debug_loc_escn))
3533 FIND(need_dwarf2, ".zdebug_loc", debug_loc_escn)
3535 FIND( need_dwarf2, ".debug_frame", debug_frame_escn)
3536 if (!ML_(sli_is_valid)(debug_frame_escn))
3537 FIND(need_dwarf2, ".zdebug_frame", debug_frame_escn)
3539 FIND( need_dwarf2, ".debug_addr", debug_addr_escn)
3540 if (!ML_(sli_is_valid)(debug_addr_escn))
3541 FIND(need_dwarf2, ".zdebug_addr", debug_addr_escn)
3543 FIND( need_dwarf2, ".debug_str_offsets", debug_str_offsets_escn)
3544 if (!ML_(sli_is_valid)(debug_str_offsets_escn))
3545 FIND(need_dwarf2, ".zdebug_str_offsets", debug_str_offsets_escn)
3547 if (!ML_(sli_is_valid)(debugaltlink_escn))
3548 FIND( need_dwarf2, ".gnu_debugaltlink", debugaltlink_escn)
3550 FIND( need_dwarf1, ".debug", dwarf1d_escn)
3551 FIND( need_dwarf1, ".line", dwarf1l_escn)
3553 # undef FIND
3554 } /* Find all interesting sections */
3555 } /* do we have a debug image? */
3557 /* TOPLEVEL */
3558 /* Look for alternate debug image, and if found, connect |aimg|
3559 to it. */
3560 vg_assert(aimg == NULL);
3562 if (debugaltlink_escn.img != NULL) {
3563 HChar* altfile_str_m
3564 = ML_(img_strdup)(debugaltlink_escn.img,
3565 "di.fbi.3", debugaltlink_escn.ioff);
3566 UInt buildid_offset = ML_(img_strlen)(debugaltlink_escn.img,
3567 debugaltlink_escn.ioff)+1;
3569 vg_assert(buildid_offset < debugaltlink_escn.szB);
3571 HChar *altbuildid
3572 = ML_(dinfo_zalloc)("di.fbi.4",
3573 (debugaltlink_escn.szB - buildid_offset)
3574 * 2 + 1);
3576 /* The altfile might be relative to the debug file or main file.
3577 Make sure that we got the real file, not a symlink. */
3578 HChar *dbgname = di->fsm.dbgname ? di->fsm.dbgname : di->fsm.filename;
3579 HChar* rdbgname = readlink_path (dbgname);
3580 if (rdbgname == NULL)
3581 rdbgname = ML_(dinfo_strdup)("rdbgname", dbgname);
3583 for (j = 0; j < debugaltlink_escn.szB - buildid_offset; j++)
3584 VG_(sprintf)(
3585 altbuildid + 2 * j, "%02x",
3586 (UInt)ML_(img_get_UChar)(debugaltlink_escn.img,
3587 debugaltlink_escn.ioff
3588 + buildid_offset + j));
3590 /* See if we can find a matching debug file */
3591 aimg = find_debug_file( di, rdbgname, altbuildid,
3592 altfile_str_m, 0, True );
3594 ML_(dinfo_free)(rdbgname);
3596 if (altfile_str_m)
3597 ML_(dinfo_free)(altfile_str_m);
3598 ML_(dinfo_free)(altbuildid);
3601 /* TOPLEVEL */
3602 /* If we were successful in finding alternate debug image, pull various
3603 size and image addresses out of it. */
3604 if (aimg != NULL && is_elf_object_file_by_DiImage(aimg, True)) {
3606 /* Pull out and validate program header and section header info */
3607 DiOffT ehdr_aioff = 0;
3608 ElfXX_Ehdr ehdr_aimg;
3609 ML_(img_get)(&ehdr_aimg, aimg, ehdr_aioff, sizeof(ehdr_aimg));
3611 DiOffT shdr_aioff = ehdr_aimg.e_shoff;
3612 UWord shdr_anent = ehdr_aimg.e_shnum;
3613 UWord shdr_aent_szB = ehdr_aimg.e_shentsize;
3615 DiOffT shdr_strtab_aioff = DiOffT_INVALID;
3617 if (shdr_anent == 0
3618 || !ML_(img_valid)(aimg, shdr_aioff,
3619 shdr_anent * shdr_aent_szB)) {
3620 ML_(symerr)(di, True,
3621 "Missing or invalid ELF Section Header Table"
3622 " (alternate debuginfo file)");
3623 goto out;
3626 /* Also find the section header's string table, and validate. */
3627 /* checked previously by is_elf_object_file: */
3628 vg_assert(ehdr_aimg.e_shstrndx != SHN_UNDEF);
3630 // shdr_aioff is the offset of the section header table
3631 // and we need the ehdr_aimg.e_shstrndx'th entry
3632 { ElfXX_Shdr a_shdr;
3633 ML_(img_get)(&a_shdr, aimg,
3634 INDEX_BIS(shdr_aioff, ehdr_aimg.e_shstrndx,
3635 shdr_aent_szB),
3636 sizeof(a_shdr));
3637 shdr_strtab_aioff = a_shdr.sh_offset;
3638 if (!ML_(img_valid)(aimg, shdr_strtab_aioff,
3639 1/*bogus, but we don't know the real size*/)) {
3640 ML_(symerr)(di, True,
3641 "Invalid ELF Section Header String Table"
3642 " (alternate debuginfo file)");
3643 goto out;
3647 /* Find all interesting sections */
3648 for (i = 0; i < ehdr_aimg.e_shnum; i++) {
3650 # define FIND(_sec_name, _sec_escn) \
3651 do { \
3652 ElfXX_Shdr a_shdr; \
3653 ML_(img_get)(&a_shdr, aimg, \
3654 INDEX_BIS(shdr_aioff, i, shdr_aent_szB), \
3655 sizeof(a_shdr)); \
3656 if (0 == ML_(img_strcmp_c)(aimg, shdr_strtab_aioff \
3657 + a_shdr.sh_name, _sec_name)) { \
3658 if (_sec_escn.img != NULL) { \
3659 ML_(symerr)(di, True, \
3660 " alternate debuginfo section duplicates a" \
3661 " section in the main ELF file"); \
3662 goto out; \
3664 _sec_escn.img = aimg; \
3665 _sec_escn.ioff = (DiOffT)a_shdr.sh_offset; \
3666 _sec_escn.szB = a_shdr.sh_size; \
3667 if (!check_compression(&a_shdr, &_sec_escn)) { \
3668 ML_(symerr)(di, True, " Compression type is " \
3669 "unsupported"); \
3670 goto out; \
3672 vg_assert(_sec_escn.img != NULL); \
3673 vg_assert(_sec_escn.ioff != DiOffT_INVALID); \
3674 TRACE_SYMTAB( "%-18s: aioff %llu .. %llu\n", \
3675 _sec_name, \
3676 (ULong)a_shdr.sh_offset, \
3677 ((ULong)a_shdr.sh_offset) + a_shdr.sh_size - 1); \
3679 } while (0);
3681 /* NAME ElfSec */
3682 FIND(".debug_line", debug_line_alt_escn)
3683 if (!ML_(sli_is_valid)(debug_line_alt_escn))
3684 FIND(".zdebug_line", debug_line_alt_escn)
3686 FIND(".debug_info", debug_info_alt_escn)
3687 if (!ML_(sli_is_valid)(debug_info_alt_escn))
3688 FIND(".zdebug_info", debug_info_alt_escn)
3690 FIND(".debug_abbrev", debug_abbv_alt_escn)
3691 if (!ML_(sli_is_valid)(debug_abbv_alt_escn))
3692 FIND(".zdebug_abbrev", debug_abbv_alt_escn)
3694 FIND(".debug_str", debug_str_alt_escn)
3695 if (!ML_(sli_is_valid)(debug_str_alt_escn))
3696 FIND(".zdebug_str", debug_str_alt_escn)
3698 # undef FIND
3699 } /* Find all interesting sections */
3700 } /* do we have a debug image? */
3702 /* TOPLEVEL */
3703 vg_assert((symtab_escn.szB % sizeof(ElfXX_Sym)) == 0);
3705 /* TOPLEVEL */
3706 /* Read symbols */
3708 void (*read_elf_symtab)(struct _DebugInfo*, const HChar*,
3709 DiSlice*, DiSlice*, DiSlice*, Bool);
3710 # if defined(VGP_ppc64be_linux)
3711 read_elf_symtab = read_elf_symtab__ppc64be_linux;
3712 # else
3713 read_elf_symtab = read_elf_symtab__normal;
3714 # endif
3715 if (symtab_escn.img != NULL)
3716 read_elf_symtab(di, "symbol table",
3717 &symtab_escn, &strtab_escn, &opd_escn,
3718 True);
3720 if (ML_(sli_is_valid)(debug_frame_escn)) {
3721 ML_(read_callframe_info_dwarf3)( di,
3722 debug_frame_escn,
3723 0/*assume zero avma*/,
3724 False/*!is_ehframe*/ );
3727 /* TOPLEVEL */
3728 /* jrs 2006-01-01: icc-8.1 has been observed to generate
3729 binaries without debug_str sections. Don't preclude
3730 debuginfo reading for that reason, but, in
3731 read_unitinfo_dwarf2, do check that debugstr is non-NULL
3732 before using it. */
3733 if (ML_(sli_is_valid)(debug_info_escn)
3734 && ML_(sli_is_valid)(debug_abbv_escn)
3735 && ML_(sli_is_valid)(debug_line_escn)) {
3736 /* The old reader: line numbers and unwind info only */
3737 ML_(read_debuginfo_dwarf3) ( di,
3738 debug_info_escn,
3739 debug_types_escn,
3740 debug_abbv_escn,
3741 debug_line_escn,
3742 debug_str_escn,
3743 debug_str_alt_escn,
3744 debug_line_str_escn);
3745 /* The new reader: read the DIEs in .debug_info to acquire
3746 information on variable types and locations or inline info.
3747 But only if the tool asks for it, or the user requests it on
3748 the command line. */
3749 if (VG_(clo_read_var_info) /* the user or tool asked for it */
3750 || VG_(clo_read_inline_info)) {
3751 ML_(new_dwarf3_reader)(
3752 di, debug_info_escn, debug_types_escn,
3753 debug_abbv_escn, debug_line_escn,
3754 debug_str_escn, debug_ranges_escn,
3755 debug_rnglists_escn, debug_loclists_escn,
3756 debug_loc_escn, debug_info_alt_escn,
3757 debug_abbv_alt_escn, debug_line_alt_escn,
3758 debug_str_alt_escn, debug_line_str_escn,
3759 debug_addr_escn, debug_str_offsets_escn
3764 /* TOPLEVEL */
3765 // JRS 31 July 2014: dwarf-1 reading is currently broken and
3766 // therefore deactivated.
3767 //if (dwarf1d_img && dwarf1l_img) {
3768 // ML_(read_debuginfo_dwarf1) ( di, dwarf1d_img, dwarf1d_sz,
3769 // dwarf1l_img, dwarf1l_sz );
3772 # if defined(VGA_arm)
3773 /* TOPLEVEL */
3774 /* ARM32 only: read .exidx/.extab if present. Note we are
3775 reading these directly out of the mapped in (running) image.
3776 Also, read these only if no CFI based unwind info was
3777 acquired for this file.
3779 An .exidx section is always required, but the .extab section
3780 can be optionally omitted, provided that .exidx does not
3781 refer to it. If the .exidx is erroneous and does refer to
3782 .extab even though .extab is missing, the range checks done
3783 by GET_EX_U32 in ExtabEntryExtract in readexidx.c should
3784 prevent any invalid memory accesses, and cause the .extab to
3785 be rejected as invalid.
3787 FIXME:
3788 * check with m_aspacemgr that the entire [exidx_avma, +exidx_size)
3789 and [extab_avma, +extab_size) areas are readable, since we're
3790 reading this stuff out of the running image (not from a file/socket)
3791 and we don't want to segfault.
3792 * DebugInfo::exidx_bias and use text_bias instead.
3793 I think it's always the same.
3794 * remove DebugInfo::{extab_bias, exidx_svma, extab_svma} since
3795 they are never used.
3797 if (di->exidx_present
3798 && di->cfsi_used == 0
3799 && di->text_present && di->text_size > 0) {
3800 Addr text_last_svma = di->text_svma + di->text_size - 1;
3801 ML_(read_exidx)( di, (UChar*)di->exidx_avma, di->exidx_size,
3802 (UChar*)di->extab_avma, di->extab_size,
3803 text_last_svma,
3804 di->exidx_bias );
3806 # endif /* defined(VGA_arm) */
3808 } /* "Find interesting sections, read the symbol table(s), read any debug
3809 information" (a local scope) */
3811 /* TOPLEVEL */
3812 res = True;
3814 /* If reading Dwarf3 variable type/location info, print a line
3815 showing the number of variables read for each object.
3816 (Currently disabled -- is a sanity-check mechanism for
3817 exp-sgcheck.) */
3818 if (0 && VG_(clo_read_var_info)) {
3819 UWord nVars = 0;
3820 if (di->varinfo) {
3821 for (j = 0; j < VG_(sizeXA)(di->varinfo); j++) {
3822 OSet* /* of DiAddrRange */ scope
3823 = *(OSet**)VG_(indexXA)(di->varinfo, j);
3824 vg_assert(scope);
3825 VG_(OSetGen_ResetIter)( scope );
3826 while (True) {
3827 DiAddrRange* range = VG_(OSetGen_Next)( scope );
3828 if (!range) break;
3829 vg_assert(range->vars);
3830 Word w = VG_(sizeXA)(range->vars);
3831 vg_assert(w >= 0);
3832 if (0) VG_(printf)("range %#lx %#lx %ld\n",
3833 range->aMin, range->aMax, w);
3834 nVars += (UWord)w;
3838 VG_(umsg)("VARINFO: %7lu vars %7lu text_size %s\n",
3839 nVars, di->text_size, di->fsm.filename);
3841 /* TOPLEVEL */
3843 out:
3845 /* Last, but not least, detach from the image(s). */
3846 if (mimg) ML_(img_done)(mimg);
3847 if (dimg) ML_(img_done)(dimg);
3848 if (aimg) ML_(img_done)(aimg);
3850 return res;
3851 } /* out: */
3853 /* NOTREACHED */
3856 Bool ML_(check_elf_and_get_rw_loads) ( Int fd, const HChar* filename, Int * rw_load_count )
3858 Bool res, ok;
3859 UWord i;
3860 DiImage* mimg = NULL;
3861 DiOffT ehdr_mioff = 0;
3862 DiOffT phdr_mioff = 0;
3863 UWord phdr_mnent = 0U;
3864 UWord phdr_ment_szB = 0U;
3865 ElfXX_Phdr previous_rw_a_phdr;
3867 res = False;
3869 mimg = ML_(img_from_fd)(fd, filename);
3870 if (mimg == NULL) {
3871 VG_(message)(Vg_UserMsg, "warning: connection to image %s failed\n",
3872 filename );
3873 VG_(message)(Vg_UserMsg, " cannot read program headers \n" );
3874 return False;
3877 ok = is_elf_object_file_by_DiImage(mimg, False);
3878 if (!ok) {
3879 goto out;
3882 ElfXX_Ehdr ehdr_m;
3883 Elf64_Word flag_x;
3884 #if defined(VGA_amd64) || defined(VGA_ppc64be) || defined(VGA_ppc64le) || defined(VGA_arm) || defined(VGA_arm64)
3885 flag_x = PF_X;
3886 #else
3887 flag_x = 0;
3888 #endif
3890 #if defined(VGO_solaris)
3891 flag_x = 0;
3892 #endif
3894 vg_assert(ehdr_mioff == 0); // ensured by its initialisation
3895 ok = ML_(img_valid)(mimg, ehdr_mioff, sizeof(ehdr_m));
3896 vg_assert(ok); // ML_(is_elf_object_file) should ensure this
3897 ML_(img_get)(&ehdr_m, mimg, ehdr_mioff, sizeof(ehdr_m));
3899 phdr_mioff = ehdr_mioff + ehdr_m.e_phoff;
3900 phdr_mnent = ehdr_m.e_phnum;
3901 phdr_ment_szB = ehdr_m.e_phentsize;
3903 /* Sets p_memsz to 0 to indicate we have not yet a previous a_phdr. */
3904 previous_rw_a_phdr.p_memsz = 0;
3906 for (i = 0U; i < phdr_mnent; i++) {
3907 ElfXX_Phdr a_phdr;
3908 ML_(img_get)(&a_phdr, mimg,
3909 INDEX_BIS(phdr_mioff, i, phdr_ment_szB),
3910 sizeof(a_phdr));
3912 if (a_phdr.p_type == PT_LOAD) {
3913 if (a_phdr.p_memsz > 0) {
3914 if (((a_phdr.p_flags & (PF_R | PF_W)) == (PF_R | PF_W)) &&
3915 ((a_phdr.p_flags & flag_x) == 0)) {
3916 ++*rw_load_count;
3917 if (VG_(debugLog_getLevel)() > 1)
3918 VG_(message)(Vg_DebugMsg, "check_elf_and_get_rw_loads: "
3919 "++*rw_load_count to %d for %s "
3920 "p_vaddr %#lx p_offset %lu, p_filesz %lu\n",
3921 *rw_load_count, filename,
3922 (UWord)a_phdr.p_vaddr, (UWord)a_phdr.p_offset,
3923 (UWord)a_phdr.p_filesz);
3925 * Hold your horses
3926 * Just because The ELF file contains 2 RW PT_LOAD segments
3927 * doesn't mean that Valgrind will also make 2 calls to
3928 * VG_(di_notify_mmap): in some cases, the 2 NSegments will get
3929 * merged and VG_(di_notify_mmap) only gets called once.
3930 * How to detect that the segments will be merged ?
3931 * Logically, they will be merged if the first segment ends
3932 * at the beginning of the second segment:
3933 * Seg1 virtual address + Seg1 segment_size
3934 * == Seg2 virtual address.
3935 * However, it is not very clear how the file section will be
3936 * loaded: the PT_LOAD specifies a file size and a memory size.
3937 * Logically, the memory size should be used in the above
3938 * condition, but strangely enough, in some cases the file size
3939 * can be smaller than the memory size. And that then result in
3940 * an "anonymous" mapping done between the 2 segments that
3941 * otherwise would be consecutive.
3942 * This has been seen in an executable linked by the mold linker
3943 * (see bug 473944). In this case, the file segments were loaded
3944 * with a "page rounded up" file size (observed on RHEL 8.6,
3945 * ld-2.28.so, mold 1.5.1).
3946 * However, in FreeBSD with lld (see 452802 and 473944), rounding
3947 * up p_filesz in the below condition makes at least one test
3948 * fail.
3949 * As on the mold case, the below condition correctly ensures
3950 * the 2 different segments loaded separately are both counted
3951 * here, we use the non rounded up p_filesz.
3952 * This is all a nightmare/hack. Something cleaner should be
3953 * done than trying to guess here if segments will or will not
3954 * be merged later depending on how the loader will load
3955 * with or without rounding up.
3956 * */
3957 if (previous_rw_a_phdr.p_memsz > 0 &&
3958 ehdr_m.e_type == ET_EXEC &&
3959 previous_rw_a_phdr.p_vaddr + previous_rw_a_phdr.p_filesz
3960 == a_phdr.p_vaddr)
3962 --*rw_load_count;
3963 if (VG_(debugLog_getLevel)() > 1)
3964 VG_(message)(Vg_DebugMsg, "check_elf_and_get_rw_loads: "
3965 " --*rw_load_count to %d for %s\n",
3966 *rw_load_count, filename);
3969 previous_rw_a_phdr = a_phdr;
3973 } /* for (i = 0; i < phdr_Mnent; i++) ... */
3975 res = True;
3977 out:
3979 /* Last, but not least, detach from the image(s). */
3980 if (mimg) ML_(img_free)(mimg);
3982 return res;
3983 } /* out: */
3985 /* NOTREACHED */
3990 #endif // defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
3992 /*--------------------------------------------------------------------*/
3993 /*--- end ---*/
3994 /*--------------------------------------------------------------------*/