1 
2 /*--------------------------------------------------------------------*/
3 /*--- Reading of syms & debug info from ELF .so/executable files.  ---*/
4 /*---                                                    readelf.c ---*/
5 /*--------------------------------------------------------------------*/
6 
7 /*
8    This file is part of Valgrind, a dynamic binary instrumentation
9    framework.
10 
11    Copyright (C) 2000-2013 Julian Seward
12       jseward@acm.org
13 
14    This program is free software; you can redistribute it and/or
15    modify it under the terms of the GNU General Public License as
16    published by the Free Software Foundation; either version 2 of the
17    License, or (at your option) any later version.
18 
19    This program is distributed in the hope that it will be useful, but
20    WITHOUT ANY WARRANTY; without even the implied warranty of
21    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22    General Public License for more details.
23 
24    You should have received a copy of the GNU General Public License
25    along with this program; if not, write to the Free Software
26    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27    02111-1307, USA.
28 
29    The GNU General Public License is contained in the file COPYING.
30 */
31 
32 #if defined(VGO_linux)
33 
34 #include "pub_core_basics.h"
35 #include "pub_core_vki.h"
36 #include "pub_core_debuginfo.h"
37 #include "pub_core_libcbase.h"
38 #include "pub_core_libcprint.h"
39 #include "pub_core_libcassert.h"
40 #include "pub_core_machine.h"      /* VG_ELF_CLASS */
41 #include "pub_core_options.h"
42 #include "pub_core_oset.h"
43 #include "pub_core_tooliface.h"    /* VG_(needs) */
44 #include "pub_core_xarray.h"
45 #include "priv_misc.h"             /* dinfo_zalloc/free/strdup */
46 #include "priv_image.h"
47 #include "priv_d3basics.h"
48 #include "priv_tytypes.h"
49 #include "priv_storage.h"
50 #include "priv_readelf.h"          /* self */
51 #include "priv_readdwarf.h"        /* 'cos ELF contains DWARF */
52 #include "priv_readdwarf3.h"
53 #include "priv_readexidx.h"
54 
55 /* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
56 #include <elf.h>
57 /* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
58 
59 /*------------------------------------------------------------*/
60 /*--- 32/64-bit parameterisation                           ---*/
61 /*------------------------------------------------------------*/
62 
63 /* For all the ELF macros and types which specify '32' or '64',
64    select the correct variant for this platform and give it
65    an 'XX' name.  Then use the 'XX' variant consistently in
66    the rest of this file.
67 */
68 #if VG_WORDSIZE == 4
69 #  define  ElfXX_Ehdr     Elf32_Ehdr
70 #  define  ElfXX_Shdr     Elf32_Shdr
71 #  define  ElfXX_Phdr     Elf32_Phdr
72 #  define  ElfXX_Nhdr     Elf32_Nhdr
73 #  define  ElfXX_Sym      Elf32_Sym
74 #  define  ElfXX_Off      Elf32_Off
75 #  define  ElfXX_Word     Elf32_Word
76 #  define  ElfXX_Addr     Elf32_Addr
77 #  define  ElfXX_Dyn      Elf32_Dyn
78 #  define  ELFXX_ST_BIND  ELF32_ST_BIND
79 #  define  ELFXX_ST_TYPE  ELF32_ST_TYPE
80 
81 #elif VG_WORDSIZE == 8
82 #  define  ElfXX_Ehdr     Elf64_Ehdr
83 #  define  ElfXX_Shdr     Elf64_Shdr
84 #  define  ElfXX_Phdr     Elf64_Phdr
85 #  define  ElfXX_Nhdr     Elf64_Nhdr
86 #  define  ElfXX_Sym      Elf64_Sym
87 #  define  ElfXX_Off      Elf64_Off
88 #  define  ElfXX_Word     Elf64_Word
89 #  define  ElfXX_Addr     Elf64_Addr
90 #  define  ElfXX_Dyn      Elf64_Dyn
91 #  define  ELFXX_ST_BIND  ELF64_ST_BIND
92 #  define  ELFXX_ST_TYPE  ELF64_ST_TYPE
93 
94 #else
95 # error "VG_WORDSIZE should be 4 or 8"
96 #endif
97 
98 
99 /*------------------------------------------------------------*/
100 /*---                                                      ---*/
101 /*--- Read symbol table and line info from ELF files.      ---*/
102 /*---                                                      ---*/
103 /*------------------------------------------------------------*/
104 
105 /* readelf.c parses ELF files and acquires symbol table info from
106    them.  It calls onwards to readdwarf.c to read DWARF2/3 line number
107    and call frame info found. */
108 
109 /* Identify an ELF object file by peering at the first few bytes of
110    it. */
111 
ML_(is_elf_object_file)112 Bool ML_(is_elf_object_file)( const void* image, SizeT n_image, Bool rel_ok )
113 {
114    const ElfXX_Ehdr* ehdr = image;
115    Int ok = 1;
116 
117    if (n_image < sizeof(ElfXX_Ehdr))
118       return False;
119 
120    ok &= (ehdr->e_ident[EI_MAG0] == 0x7F
121           && ehdr->e_ident[EI_MAG1] == 'E'
122           && ehdr->e_ident[EI_MAG2] == 'L'
123           && ehdr->e_ident[EI_MAG3] == 'F');
124    ok &= (ehdr->e_ident[EI_CLASS] == VG_ELF_CLASS
125           && ehdr->e_ident[EI_DATA] == VG_ELF_DATA2XXX
126           && ehdr->e_ident[EI_VERSION] == EV_CURRENT);
127    ok &= (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN
128           || (rel_ok && ehdr->e_type == ET_REL));
129    ok &= (ehdr->e_machine == VG_ELF_MACHINE);
130    ok &= (ehdr->e_version == EV_CURRENT);
131    ok &= (ehdr->e_shstrndx != SHN_UNDEF);
132    ok &= (ehdr->e_shoff != 0 && ehdr->e_shnum != 0);
133    ok &= ((ehdr->e_phoff != 0 && ehdr->e_phnum != 0)
134           || ehdr->e_type == ET_REL);
135 
136    return ok ? True : False;
137 }
138 
139 
140 /* The same thing, but operating on a DiImage instead. */
141 
is_elf_object_file_by_DiImage(DiImage * img,Bool rel_ok)142 static Bool is_elf_object_file_by_DiImage( DiImage* img, Bool rel_ok )
143 {
144    /* Be sure this doesn't make the frame too big. */
145    vg_assert(sizeof(ElfXX_Ehdr) <= 512);
146 
147    ElfXX_Ehdr ehdr;
148    if (!ML_(img_valid)(img, 0, sizeof(ehdr)))
149       return False;
150 
151    ML_(img_get)(&ehdr, img, 0, sizeof(ehdr));
152    return ML_(is_elf_object_file)( &ehdr, sizeof(ehdr), rel_ok );
153 }
154 
155 
156 /* Show a raw ELF symbol, given its in-image address and name. */
157 
158 static
show_raw_elf_symbol(DiImage * strtab_img,Int i,const ElfXX_Sym * sym,DiOffT sym_name_ioff,Addr sym_svma,Bool ppc64_linux_format)159 void show_raw_elf_symbol ( DiImage* strtab_img,
160                            Int i,
161                            const ElfXX_Sym* sym,
162                            DiOffT sym_name_ioff, Addr sym_svma,
163                            Bool ppc64_linux_format )
164 {
165    const HChar* space = ppc64_linux_format ? "                  " : "";
166    VG_(printf)("raw symbol [%4d]: ", i);
167    switch (ELFXX_ST_BIND(sym->st_info)) {
168       case STB_LOCAL:  VG_(printf)("LOC "); break;
169       case STB_GLOBAL: VG_(printf)("GLO "); break;
170       case STB_WEAK:   VG_(printf)("WEA "); break;
171       case STB_LOPROC: VG_(printf)("lop "); break;
172       case STB_HIPROC: VG_(printf)("hip "); break;
173       default:         VG_(printf)("??? "); break;
174    }
175    switch (ELFXX_ST_TYPE(sym->st_info)) {
176       case STT_NOTYPE:  VG_(printf)("NOT "); break;
177       case STT_OBJECT:  VG_(printf)("OBJ "); break;
178       case STT_FUNC:    VG_(printf)("FUN "); break;
179       case STT_SECTION: VG_(printf)("SEC "); break;
180       case STT_FILE:    VG_(printf)("FIL "); break;
181       case STT_LOPROC:  VG_(printf)("lop "); break;
182       case STT_HIPROC:  VG_(printf)("hip "); break;
183       default:          VG_(printf)("??? "); break;
184    }
185    HChar* sym_name = NULL;
186    if (sym->st_name)
187       sym_name = ML_(img_strdup)(strtab_img, "di.sres.1", sym_name_ioff);
188    VG_(printf)(": svma %#010lx, %ssz %4llu  %s\n",
189                sym_svma, space, (ULong)(sym->st_size + 0UL),
190                (sym_name ? sym_name : "NONAME") );
191    if (sym_name)
192       ML_(dinfo_free)(sym_name);
193 }
194 
195 
196 /* Decide whether SYM is something we should collect, and if so, copy
197    relevant info to the _OUT arguments.  For {x86,amd64,ppc32}-linux
198    this is straightforward - the name, address, size are copied out
199    unchanged.
200 
201    There is a bit of a kludge re data symbols (see KLUDGED BSS CHECK
202    below): we assume that the .bss is mapped immediately after .data,
203    and so accept any data symbol which exists in the range [start of
204    .data, size of .data + size of .bss).  I don't know if this is
205    really correct/justifiable, or not.
206 
207    For ppc64be-linux it's more complex.  If the symbol is seen to be in
208    the .opd section, it is taken to be a function descriptor, and so
209    a dereference is attempted, in order to get hold of the real entry
210    point address.  Also as part of the dereference, there is an attempt
211    to calculate the TOC pointer (R2 value) associated with the symbol.
212 
213    To support the ppc64be-linux pre-"dotless" ABI (prior to gcc 4.0.0),
214    if the symbol is seen to be outside the .opd section and its name
215    starts with a dot, an .opd deference is not attempted, and no TOC
216    pointer is calculated, but the leading dot is removed from the
217    name.
218 
219    As a result, on ppc64be-linux, the caller of this function may have
220    to piece together the real size, address, name of the symbol from
221    multiple calls to this function.  Ugly and confusing.
222 */
223 static
get_elf_symbol_info(struct _DebugInfo * di,const ElfXX_Sym * sym,DiOffT sym_name_ioff,const DiSlice * escn_strtab,Addr sym_svma,Bool symtab_in_debug,const DiSlice * escn_opd,PtrdiffT opd_bias,DiOffT * sym_name_out_ioff,SymAVMAs * sym_avmas_out,Int * sym_size_out,Bool * from_opd_out,Bool * is_text_out,Bool * is_ifunc)224 Bool get_elf_symbol_info (
225         /* INPUTS */
226         struct _DebugInfo* di, /* containing DebugInfo */
227         const ElfXX_Sym* sym,        /* ELF symbol */
228         DiOffT     sym_name_ioff, /* name, may be absent (DiOffT_INVALID) */
229         const DiSlice*   escn_strtab,   /* holds the name */
230         Addr       sym_svma,   /* address as stated in the object file */
231         Bool       symtab_in_debug, /* symbol table is in the debug file */
232         const DiSlice*   escn_opd,   /* the .opd (ppc64be-linux only) */
233         PtrdiffT   opd_bias,   /* for biasing AVMAs found in .opd */
234         /* OUTPUTS */
235         DiOffT* sym_name_out_ioff, /* name (in strtab) we should record */
236         SymAVMAs* sym_avmas_out,     /* sym avmas we should record */
237         Int*    sym_size_out,   /* symbol size */
238         Bool*   from_opd_out,   /* ppc64be-linux only: did we deref an
239                                   .opd entry? */
240         Bool*   is_text_out,    /* is this a text symbol? */
241         Bool*   is_ifunc        /* is this a  STT_GNU_IFUNC function ?*/
242      )
243 {
244    Bool plausible;
245 #  if defined(VGP_ppc64be_linux)
246    Bool is_in_opd;
247 #  endif
248    Bool in_text, in_data, in_sdata, in_rodata, in_bss, in_sbss;
249    Addr text_svma, data_svma, sdata_svma, rodata_svma, bss_svma, sbss_svma;
250    PtrdiffT text_bias, data_bias, sdata_bias, rodata_bias, bss_bias, sbss_bias;
251 
252    /* Set defaults */
253    *sym_name_out_ioff = sym_name_ioff;
254    (*sym_avmas_out).main   = sym_svma; /* we will bias this shortly */
255    *is_text_out       = True;
256    SET_TOCPTR_AVMA(*sym_avmas_out, 0);   /* default to unknown/inapplicable */
257    SET_LOCAL_EP_AVMA(*sym_avmas_out, 0); /* default to unknown/inapplicable */
258    *from_opd_out      = False;
259    *is_ifunc          = False;
260 
261    /* Get the symbol size, but restrict it to fit in a signed 32 bit
262       int.  Also, deal with the stupid case of negative size by making
263       the size be 1.  Note that sym->st_size has type UWord,
264       effectively. */
265    { Word size_tmp = (Word)sym->st_size;
266      Word max_Int  = (1LL << 31) - 1;
267      if (size_tmp < 0)       size_tmp = 1;
268      if (size_tmp > max_Int) size_tmp = max_Int;
269      *sym_size_out = (Int)size_tmp;
270    }
271    /* After this point refer only to *sym_size_out and not to
272       sym->st_size. */
273 
274    /* Figure out if we're interested in the symbol.  Firstly, is it of
275       the right flavour?  */
276    plausible
277       = (ELFXX_ST_BIND(sym->st_info) == STB_GLOBAL
278          || ELFXX_ST_BIND(sym->st_info) == STB_LOCAL
279          || ELFXX_ST_BIND(sym->st_info) == STB_WEAK
280         )
281         &&
282         (ELFXX_ST_TYPE(sym->st_info) == STT_FUNC
283          || ELFXX_ST_TYPE(sym->st_info) == STT_OBJECT
284 #        ifdef STT_GNU_IFUNC
285          || ELFXX_ST_TYPE(sym->st_info) == STT_GNU_IFUNC
286 #        endif
287         );
288 
289    /* Work out the svma and bias for each section as it will appear in
290       addresses in the symbol table. */
291    if (symtab_in_debug) {
292       text_svma = di->text_debug_svma;
293       text_bias = di->text_debug_bias;
294       data_svma = di->data_debug_svma;
295       data_bias = di->data_debug_bias;
296       sdata_svma = di->sdata_debug_svma;
297       sdata_bias = di->sdata_debug_bias;
298       rodata_svma = di->rodata_debug_svma;
299       rodata_bias = di->rodata_debug_bias;
300       bss_svma = di->bss_debug_svma;
301       bss_bias = di->bss_debug_bias;
302       sbss_svma = di->sbss_debug_svma;
303       sbss_bias = di->sbss_debug_bias;
304    } else {
305       text_svma = di->text_svma;
306       text_bias = di->text_bias;
307       data_svma = di->data_svma;
308       data_bias = di->data_bias;
309       sdata_svma = di->sdata_svma;
310       sdata_bias = di->sdata_bias;
311       rodata_svma = di->rodata_svma;
312       rodata_bias = di->rodata_bias;
313       bss_svma = di->bss_svma;
314       bss_bias = di->bss_bias;
315       sbss_svma = di->sbss_svma;
316       sbss_bias = di->sbss_bias;
317    }
318 
319    /* Now bias (*sym_avmas_out).main accordingly by figuring out exactly which
320       section the symbol is from and bias accordingly.  Screws up if
321       the previously deduced section svma address ranges are wrong. */
322    if (di->text_present
323        && di->text_size > 0
324        && sym_svma >= text_svma
325        && sym_svma < text_svma + di->text_size) {
326       *is_text_out = True;
327       (*sym_avmas_out).main += text_bias;
328    } else
329    if (di->data_present
330        && di->data_size > 0
331        && sym_svma >= data_svma
332        && sym_svma < data_svma + di->data_size) {
333       *is_text_out = False;
334       (*sym_avmas_out).main += data_bias;
335    } else
336    if (di->sdata_present
337        && di->sdata_size > 0
338        && sym_svma >= sdata_svma
339        && sym_svma < sdata_svma + di->sdata_size) {
340       *is_text_out = False;
341       (*sym_avmas_out).main += sdata_bias;
342    } else
343    if (di->rodata_present
344        && di->rodata_size > 0
345        && sym_svma >= rodata_svma
346        && sym_svma < rodata_svma + di->rodata_size) {
347       *is_text_out = False;
348       (*sym_avmas_out).main += rodata_bias;
349    } else
350    if (di->bss_present
351        && di->bss_size > 0
352        && sym_svma >= bss_svma
353        && sym_svma < bss_svma + di->bss_size) {
354       *is_text_out = False;
355       (*sym_avmas_out).main += bss_bias;
356    } else
357    if (di->sbss_present
358        && di->sbss_size > 0
359        && sym_svma >= sbss_svma
360        && sym_svma < sbss_svma + di->sbss_size) {
361       *is_text_out = False;
362       (*sym_avmas_out).main += sbss_bias;
363    } else {
364       /* Assume it's in .text.  Is this a good idea? */
365       *is_text_out = True;
366       (*sym_avmas_out).main += text_bias;
367    }
368 
369 #  ifdef STT_GNU_IFUNC
370    /* Check for indirect functions. */
371    if (*is_text_out
372        && ELFXX_ST_TYPE(sym->st_info) == STT_GNU_IFUNC) {
373        *is_ifunc = True;
374    }
375 #  endif
376 
377 #  if defined(VGP_ppc64be_linux)
378    /* Allow STT_NOTYPE in the very special case where we're running on
379       ppc64be-linux and the symbol is one which the .opd-chasing hack
380       below will chase. */
381    if (!plausible
382        && *is_text_out
383        && ELFXX_ST_TYPE(sym->st_info) == STT_NOTYPE
384        && *sym_size_out > 0
385        && di->opd_present
386        && di->opd_size > 0
387        && (*sym_avmas_out).main >= di->opd_avma
388        && (*sym_avmas_out).main <  di->opd_avma + di->opd_size)
389       plausible = True;
390 #  endif
391 
392    if (!plausible)
393       return False;
394 
395    /* Ignore if nameless. */
396    if (sym_name_ioff == DiOffT_INVALID
397        || /* VG_(strlen)(sym_name) == 0 */
398           /* equivalent but cheaper ... */
399           ML_(img_get_UChar)(escn_strtab->img, sym_name_ioff) == '\0') {
400       if (TRACE_SYMTAB_ENABLED) {
401          HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
402                                            "di.gesi.1", sym_name_ioff);
403          TRACE_SYMTAB("    ignore -- nameless: %s\n", sym_name);
404          if (sym_name) ML_(dinfo_free)(sym_name);
405       }
406       return False;
407    }
408 
409    /* Ignore if zero-sized.  Except on Android:
410 
411       On Android 2.3.5, some of the symbols that Memcheck needs to
412       intercept (for noise reduction purposes) have zero size, due to
413       lack of .size directives in handwritten assembly sources.  So we
414       can't reject them out of hand -- instead give them a bogusly
415       large size and let canonicaliseSymtab trim them so they don't
416       overlap any following symbols.  At least the following symbols
417       are known to be affected:
418 
419       in /system/lib/libc.so: strlen strcmp strcpy memcmp memcpy
420       in /system/bin/linker:  __dl_strcmp __dl_strlen
421    */
422    if (*sym_size_out == 0) {
423 #     if defined(VGPV_arm_linux_android) \
424          || defined(VGPV_x86_linux_android) \
425          || defined(VGPV_mips32_linux_android) \
426          || defined(VGPV_arm64_linux_android)
427       *sym_size_out = 2048;
428 #     else
429       if (TRACE_SYMTAB_ENABLED) {
430          HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
431                                            "di.gesi.2", sym_name_ioff);
432          TRACE_SYMTAB("    ignore -- size=0: %s\n", sym_name);
433          if (sym_name) ML_(dinfo_free)(sym_name);
434       }
435       return False;
436 #     endif
437    }
438 
439    /* This seems to significantly reduce the number of junk
440       symbols, and particularly reduces the number of
441       overlapping address ranges.  Don't ask me why ... */
442    if ((Int)sym->st_value == 0) {
443       if (TRACE_SYMTAB_ENABLED) {
444          HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
445                                            "di.gesi.3", sym_name_ioff);
446          TRACE_SYMTAB( "    ignore -- valu=0: %s\n", sym_name);
447          if (sym_name) ML_(dinfo_free)(sym_name);
448       }
449       return False;
450    }
451 
452    /* If it's apparently in a GOT or PLT, it's really a reference to a
453       symbol defined elsewhere, so ignore it. */
454    if (di->got_present
455        && di->got_size > 0
456        && (*sym_avmas_out).main >= di->got_avma
457        && (*sym_avmas_out).main <  di->got_avma + di->got_size) {
458       if (TRACE_SYMTAB_ENABLED) {
459          HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
460                                            "di.gesi.4", sym_name_ioff);
461          TRACE_SYMTAB("    ignore -- in GOT: %s\n", sym_name);
462          if (sym_name) ML_(dinfo_free)(sym_name);
463       }
464       return False;
465    }
466    if (di->plt_present
467        && di->plt_size > 0
468        && (*sym_avmas_out).main >= di->plt_avma
469        && (*sym_avmas_out).main <  di->plt_avma + di->plt_size) {
470       if (TRACE_SYMTAB_ENABLED) {
471          HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
472                                            "di.gesi.5", sym_name_ioff);
473          TRACE_SYMTAB("    ignore -- in PLT: %s\n", sym_name);
474          if (sym_name) ML_(dinfo_free)(sym_name);
475       }
476       return False;
477    }
478 
479    /* ppc64be-linux nasty hack: if the symbol is in an .opd section,
480       then really what we have is the address of a function
481       descriptor.  So use the first word of that as the function's
482       text.
483 
484       See thread starting at
485       http://gcc.gnu.org/ml/gcc-patches/2004-08/msg00557.html
486    */
487 #  if defined(VGP_ppc64be_linux)
488    /* Host and guest may have different Endianess, used by BE only */
489    is_in_opd = False;
490 #  endif
491 
492    if (di->opd_present
493        && di->opd_size > 0
494        && (*sym_avmas_out).main >= di->opd_avma
495        && (*sym_avmas_out).main <  di->opd_avma + di->opd_size) {
496 #     if !defined(VGP_ppc64be_linux)
497       if (TRACE_SYMTAB_ENABLED) {
498          HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
499                                            "di.gesi.6", sym_name_ioff);
500          TRACE_SYMTAB("    ignore -- in OPD: %s\n", sym_name);
501          if (sym_name) ML_(dinfo_free)(sym_name);
502       }
503       return False;
504 #     else
505       Int    offset_in_opd;
506       Bool   details = 1||False;
507 
508       if (details)
509          TRACE_SYMTAB("opdXXX: opd_bias %p, sym_svma_out %p\n",
510                       (void*)(opd_bias), (void*)(*sym_avmas_out).main);
511 
512       if (!VG_IS_8_ALIGNED((*sym_avmas_out).main)) {
513          if (TRACE_SYMTAB_ENABLED) {
514             HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
515                                               "di.gesi.6a", sym_name_ioff);
516             TRACE_SYMTAB("    ignore -- not 8-aligned: %s\n", sym_name);
517             if (sym_name) ML_(dinfo_free)(sym_name);
518          }
519          return False;
520       }
521 
522       /* (*sym_avmas_out).main is a avma pointing into the .opd section.  We
523          know the vma of the opd section start, so we can figure out
524          how far into the opd section this is. */
525 
526       offset_in_opd = (Addr)(*sym_avmas_out).main - (Addr)(di->opd_avma);
527       if (offset_in_opd < 0 || offset_in_opd >= di->opd_size) {
528          if (TRACE_SYMTAB_ENABLED) {
529             HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
530                                               "di.gesi.6a", sym_name_ioff);
531             TRACE_SYMTAB("    ignore -- invalid OPD offset: %s\n", sym_name);
532             if (sym_name) ML_(dinfo_free)(sym_name);
533          }
534          return False;
535       }
536 
537       /* Now we want to know what's at that offset in the .opd
538          section.  We can't look in the running image since it won't
539          necessarily have been mapped.  But we can consult the oimage.
540          opd_img is the start address of the .opd in the oimage.
541          Hence: */
542 
543       ULong fn_descr[2]; /* is actually 3 words, but we need only 2 */
544       if (!ML_(img_valid)(escn_opd->img, escn_opd->ioff + offset_in_opd,
545                           sizeof(fn_descr))) {
546          if (TRACE_SYMTAB_ENABLED) {
547             HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
548                                               "di.gesi.6b", sym_name_ioff);
549             TRACE_SYMTAB("    ignore -- invalid OPD fn_descr offset: %s\n",
550                          sym_name);
551             if (sym_name) ML_(dinfo_free)(sym_name);
552 
553          }
554          return False;
555       }
556 
557       /* This can't fail now, because we just checked the offset
558          above. */
559       ML_(img_get)(&fn_descr[0], escn_opd->img,
560                    escn_opd->ioff + offset_in_opd, sizeof(fn_descr));
561 
562       if (details)
563          TRACE_SYMTAB("opdXXY: offset %d,  fn_descr %p\n",
564                       offset_in_opd, fn_descr);
565       if (details)
566          TRACE_SYMTAB("opdXXZ: *fn_descr %p\n", (void*)(fn_descr[0]));
567 
568       /* opd_bias is the what we have to add to SVMAs found in .opd to
569          get plausible .text AVMAs for the entry point, and .data
570          AVMAs (presumably) for the TOC locations.  We use the caller
571          supplied value (which is di->text_bias) for both of these.
572          Not sure why that is correct - it seems to work, and sounds
573          OK for fn_descr[0], but surely we need to use the data bias
574          and not the text bias for fn_descr[1] ?  Oh Well.
575       */
576       (*sym_avmas_out).main   = fn_descr[0] + opd_bias;
577       SET_TOCPTR_AVMA(*sym_avmas_out, fn_descr[1] + opd_bias);
578       *from_opd_out   = True;
579       is_in_opd = True;
580 
581       /* Do a final sanity check: if the symbol falls outside the
582          DebugInfo's mapped range, ignore it.  Since (*sym_avmas_out).main has
583          been updated, that can be achieved simply by falling through
584          to the test below. */
585 
586 #     endif /* ppc64-linux nasty hack */
587    }
588 
589    /* Here's yet another ppc64-linux hack.  Get rid of leading dot if
590       the symbol is outside .opd. */
591 #  if defined(VGP_ppc64be_linux)
592    if (di->opd_size > 0
593        && !is_in_opd
594        && *sym_name_out_ioff != DiOffT_INVALID
595        && ML_(img_get_UChar)(escn_strtab->img, *sym_name_out_ioff) == '.') {
596       vg_assert(!(*from_opd_out));
597       (*sym_name_out_ioff)++;
598    }
599 #  endif
600 
601    /* If no part of the symbol falls within the mapped range,
602       ignore it. */
603 
604    in_text
605       = di->text_present
606         && di->text_size > 0
607         && !((*sym_avmas_out).main + *sym_size_out <= di->text_avma
608              || (*sym_avmas_out).main >= di->text_avma + di->text_size);
609 
610    in_data
611       = di->data_present
612         && di->data_size > 0
613         && !((*sym_avmas_out).main + *sym_size_out <= di->data_avma
614              || (*sym_avmas_out).main >= di->data_avma + di->data_size);
615 
616    in_sdata
617       = di->sdata_present
618         && di->sdata_size > 0
619         && !((*sym_avmas_out).main + *sym_size_out <= di->sdata_avma
620              || (*sym_avmas_out).main >= di->sdata_avma + di->sdata_size);
621 
622    in_rodata
623       = di->rodata_present
624         && di->rodata_size > 0
625         && !((*sym_avmas_out).main + *sym_size_out <= di->rodata_avma
626              || (*sym_avmas_out).main >= di->rodata_avma + di->rodata_size);
627 
628    in_bss
629       = di->bss_present
630         && di->bss_size > 0
631         && !((*sym_avmas_out).main + *sym_size_out <= di->bss_avma
632              || (*sym_avmas_out).main >= di->bss_avma + di->bss_size);
633 
634    in_sbss
635       = di->sbss_present
636         && di->sbss_size > 0
637         && !((*sym_avmas_out).main + *sym_size_out <= di->sbss_avma
638              || (*sym_avmas_out).main >= di->sbss_avma + di->sbss_size);
639 
640 
641    if (*is_text_out) {
642       /* This used to reject any symbol falling outside the text
643          segment ("if (!in_text) ...").  Now it is relaxed slightly,
644          to reject only symbols which fall outside the area mapped
645          r-x.  This is in accordance with r7427.  See
646          "Comment_Regarding_Text_Range_Checks" in storage.c for
647          background. */
648       Bool in_rx;
649       vg_assert(di->fsm.have_rx_map);
650       /* This could actually wrap around and cause
651          ML_(find_rx_mapping) to assert.  But that seems so unlikely,
652          let's wait for it to happen before fixing it. */
653       in_rx = (ML_(find_rx_mapping)(
654                       di,
655                       (*sym_avmas_out).main,
656                       (*sym_avmas_out).main + *sym_size_out) != NULL);
657       if (in_text)
658          vg_assert(in_rx);
659       if (!in_rx) {
660          TRACE_SYMTAB(
661             "ignore -- %#lx .. %#lx outside .text svma range %#lx .. %#lx\n",
662             (*sym_avmas_out).main, (*sym_avmas_out).main + *sym_size_out,
663             di->text_avma,
664             di->text_avma + di->text_size);
665          return False;
666       }
667    } else {
668      if (!(in_data || in_sdata || in_rodata || in_bss || in_sbss)) {
669          TRACE_SYMTAB(
670             "ignore -- %#lx .. %#lx outside .data / .sdata / .rodata "
671             "/ .bss / .sbss svma ranges\n",
672             (*sym_avmas_out).main, (*sym_avmas_out).main + *sym_size_out);
673          return False;
674       }
675    }
676 
677 #  if defined(VGP_ppc64be_linux)
678    if (di->opd_present && di->opd_size > 0) {
679       vg_assert((*sym_avmas_out).main + *sym_size_out <= di->opd_avma
680                 || (*sym_avmas_out).main >= di->opd_avma + di->opd_size);
681    }
682 #endif
683 
684 #  if defined(VGP_ppc64le_linux)
685    /* PPC64 LE ABI uses three bits in the st_other field to indicate the number
686     * of instructions between the function's global and local entry points. An
687     * offset of 0 indicates that there is one entry point.  The value must be:
688     *
689     * 0 - one entry point, local and global are the same
690     * 1 - reserved
691     * 2 - local entry point is one instruction after the global entry point
692     * 3 - local entry point is two instructions after the global entry point
693     * 4 - local entry point is four instructions after the global entry point
694     * 5 - local entry point is eight instructions after the global entry point
695     * 6 - local entry point is sixteen instructions after the global entry point
696     * 7 - reserved
697     *
698     *  Extract the three bit field from the other field is done by:
699     *        (other_field & STO_PPC64_LOCAL_MASK) >> STO_PPC_LOCAL_BIT
700     *
701     *  where the #define values are given in include/elf/powerpc.h file for
702     *  the PPC binutils.
703     *
704     * conversion of the three bit field to bytes is given by
705     *
706     *       ((1 << bit_field) >> 2) << 2
707     */
708 
709    #define STO_PPC64_LOCAL_BIT             5
710    #define STO_PPC64_LOCAL_MASK            (7 << STO_PPC64_LOCAL_BIT)
711    {
712       unsigned int bit_field, dist_to_local_entry;
713       /* extract the other filed */
714       bit_field = (sym->st_other & STO_PPC64_LOCAL_MASK) >> STO_PPC64_LOCAL_BIT;
715 
716       if ((bit_field > 0) && (bit_field < 7)) {
717          /* store the local entry point address */
718          dist_to_local_entry = ((1 << bit_field) >> 2) << 2;
719          SET_LOCAL_EP_AVMA(*sym_avmas_out,
720                            (*sym_avmas_out).main + dist_to_local_entry);
721 
722          if (TRACE_SYMTAB_ENABLED) {
723             HChar* sym_name = ML_(img_strdup)(escn_strtab->img,
724                                              "di.gesi.5", sym_name_ioff);
725             VG_(printf)("Local entry point: %s at %#010x\n",
726 			sym_name,
727                         (unsigned int)GET_LOCAL_EP_AVMA(*sym_avmas_out));
728          }
729       }
730    }
731 #  endif
732 
733    /* Acquire! */
734    return True;
735 }
736 
737 
738 /* Read an ELF symbol table (normal or dynamic).  This one is for the
739    "normal" case ({x86,amd64,ppc32,arm,mips32,mips64, ppc64le}-linux). */
740 static
741 __attribute__((unused)) /* not referred to on all targets */
read_elf_symtab__normal(struct _DebugInfo * di,const HChar * tab_name,DiSlice * escn_symtab,DiSlice * escn_strtab,DiSlice * escn_opd,Bool symtab_in_debug)742 void read_elf_symtab__normal(
743         struct _DebugInfo* di, const HChar* tab_name,
744         DiSlice*   escn_symtab,
745         DiSlice*   escn_strtab,
746         DiSlice*   escn_opd, /* ppc64be-linux only */
747         Bool       symtab_in_debug
748      )
749 {
750    if (escn_strtab->img == NULL || escn_symtab->img == NULL) {
751       HChar buf[VG_(strlen)(tab_name) + 40];
752       VG_(sprintf)(buf, "   object doesn't have a %s", tab_name);
753       ML_(symerr)(di, False, buf);
754       return;
755    }
756 
757    TRACE_SYMTAB("\n--- Reading (ELF, standard) %s (%lld entries) ---\n",
758                 tab_name, escn_symtab->szB/sizeof(ElfXX_Sym) );
759 
760    /* Perhaps should start at i = 1; ELF docs suggest that entry
761       0 always denotes 'unknown symbol'. */
762    Word i;
763    for (i = 1; i < (Word)(escn_symtab->szB/sizeof(ElfXX_Sym)); i++) {
764       ElfXX_Sym sym;
765       ML_(img_get)(&sym, escn_symtab->img,
766                    escn_symtab->ioff + i * sizeof(ElfXX_Sym), sizeof(sym));
767       DiOffT sym_name = escn_strtab->ioff + sym.st_name;
768       Addr   sym_svma = sym.st_value;
769 
770       if (di->trace_symtab)
771         show_raw_elf_symbol(escn_strtab->img, i,
772                             &sym, sym_name, sym_svma, False);
773 
774       SymAVMAs sym_avmas_really;
775       Int    sym_size = 0;
776       Bool   from_opd = False, is_text = False, is_ifunc = False;
777       DiOffT sym_name_really = DiOffT_INVALID;
778       sym_avmas_really.main = 0;
779       SET_TOCPTR_AVMA(sym_avmas_really, 0);
780       SET_LOCAL_EP_AVMA(sym_avmas_really, 0);
781       if (get_elf_symbol_info(di, &sym, sym_name, escn_strtab,
782                               sym_svma, symtab_in_debug,
783                               escn_opd, di->text_bias,
784                               &sym_name_really,
785                               &sym_avmas_really,
786                               &sym_size,
787                               &from_opd, &is_text, &is_ifunc)) {
788 
789          DiSym  disym;
790          VG_(memset)(&disym, 0, sizeof(disym));
791          HChar* cstr = ML_(img_strdup)(escn_strtab->img,
792                                        "di.res__n.1", sym_name_really);
793          disym.avmas  = sym_avmas_really;
794          disym.pri_name  = ML_(addStr) ( di, cstr, -1 );
795          disym.sec_names = NULL;
796          disym.size      = sym_size;
797          disym.isText    = is_text;
798          disym.isIFunc   = is_ifunc;
799          if (cstr) { ML_(dinfo_free)(cstr); cstr = NULL; }
800          vg_assert(disym.pri_name);
801          vg_assert(GET_TOCPTR_AVMA(disym.avmas) == 0);
802          /* has no role except on ppc64be-linux */
803          ML_(addSym) ( di, &disym );
804 
805          if (TRACE_SYMTAB_ENABLED) {
806             TRACE_SYMTAB("    rec(%c) [%4ld]:          "
807                          "  val %#010lx, sz %4d  %s\n",
808                          is_text ? 't' : 'd',
809                          i,
810                          disym.avmas.main,
811                          (Int)disym.size,
812                          disym.pri_name
813             );
814 	    if (GET_LOCAL_EP_AVMA(disym.avmas) != 0) {
815                TRACE_SYMTAB("               local entry point %#010lx\n",
816                             GET_LOCAL_EP_AVMA(disym.avmas));
817 	    }
818          }
819 
820       }
821    }
822 }
823 
824 
825 /* Read an ELF symbol table (normal or dynamic).  This one is for
826    ppc64be-linux, which requires special treatment. */
827 
828 typedef
829    struct {
830       Addr   addr;
831       DiOffT name;
832       /* We have to store also the DiImage* so as to give context for
833          |name|.  This is not part of the key (in terms of lookup) but
834          there's no easy other way to do this.  Ugly. */
835       DiImage* img;
836    }
837    TempSymKey;
838 
839 typedef
840    struct {
841       TempSymKey key;
842       Addr       tocptr;
843       Int        size;
844       Bool       from_opd;
845       Bool       is_text;
846       Bool       is_ifunc;
847    }
848    TempSym;
849 
cmp_TempSymKey(const TempSymKey * key1,const TempSym * elem2)850 static Word cmp_TempSymKey ( const TempSymKey* key1, const TempSym* elem2 )
851 {
852    /* Stay sane ... */
853    vg_assert(key1->img == elem2->key.img);
854    vg_assert(key1->img != NULL);
855    if (key1->addr < elem2->key.addr) return -1;
856    if (key1->addr > elem2->key.addr) return 1;
857    vg_assert(key1->name != DiOffT_INVALID);
858    vg_assert(elem2->key.name != DiOffT_INVALID);
859    return (Word)ML_(img_strcmp)(key1->img, key1->name, elem2->key.name);
860 }
861 
862 static
863 __attribute__((unused)) /* not referred to on all targets */
read_elf_symtab__ppc64be_linux(struct _DebugInfo * di,const HChar * tab_name,DiSlice * escn_symtab,DiSlice * escn_strtab,DiSlice * escn_opd,Bool symtab_in_debug)864 void read_elf_symtab__ppc64be_linux(
865         struct _DebugInfo* di, const HChar* tab_name,
866         DiSlice*   escn_symtab,
867         DiSlice*   escn_strtab,
868         DiSlice*   escn_opd, /* ppc64be-linux only */
869         Bool       symtab_in_debug
870      )
871 {
872    Word        i;
873    Int         old_size;
874    Bool        modify_size, modify_tocptr;
875    OSet       *oset;
876    TempSymKey  key;
877    TempSym    *elem;
878    TempSym    *prev;
879 
880    if (escn_strtab->img == NULL || escn_symtab->img == NULL) {
881       HChar buf[VG_(strlen)(tab_name) + 40];
882       VG_(sprintf)(buf, "   object doesn't have a %s", tab_name);
883       ML_(symerr)(di, False, buf);
884       return;
885    }
886 
887    TRACE_SYMTAB("\n--- Reading (ELF, ppc64be-linux) %s (%lld entries) ---\n",
888                 tab_name, escn_symtab->szB/sizeof(ElfXX_Sym) );
889 
890    oset = VG_(OSetGen_Create)( offsetof(TempSym,key),
891                                (OSetCmp_t)cmp_TempSymKey,
892                                ML_(dinfo_zalloc), "di.respl.1",
893                                ML_(dinfo_free) );
894 
895    /* Perhaps should start at i = 1; ELF docs suggest that entry
896       0 always denotes 'unknown symbol'. */
897    for (i = 1; i < (Word)(escn_symtab->szB/sizeof(ElfXX_Sym)); i++) {
898       ElfXX_Sym sym;
899       ML_(img_get)(&sym, escn_symtab->img,
900                    escn_symtab->ioff + i * sizeof(ElfXX_Sym), sizeof(sym));
901       DiOffT sym_name = escn_strtab->ioff + sym.st_name;
902       Addr   sym_svma = sym.st_value;
903 
904       if (di->trace_symtab)
905          show_raw_elf_symbol(escn_strtab->img, i,
906                              &sym, sym_name, sym_svma, True);
907 
908       SymAVMAs sym_avmas_really;
909       Int    sym_size = 0;
910       Bool   from_opd = False, is_text = False, is_ifunc = False;
911       DiOffT sym_name_really = DiOffT_INVALID;
912       DiSym  disym;
913       VG_(memset)(&disym, 0, sizeof(disym));
914       sym_avmas_really.main = 0;
915       SET_TOCPTR_AVMA(sym_avmas_really, 0);
916       SET_LOCAL_EP_AVMA(sym_avmas_really, 0);
917       if (get_elf_symbol_info(di, &sym, sym_name, escn_strtab,
918                               sym_svma, symtab_in_debug,
919                               escn_opd, di->text_bias,
920                               &sym_name_really,
921                               &sym_avmas_really,
922                               &sym_size,
923                               &from_opd, &is_text, &is_ifunc)) {
924 
925          /* Check if we've seen this (name,addr) key before. */
926          key.addr = sym_avmas_really.main;
927          key.name = sym_name_really;
928          key.img  = escn_strtab->img;
929          prev = VG_(OSetGen_Lookup)( oset, &key );
930 
931          if (prev) {
932 
933             /* Seen it before.  Fold in whatever new info we can. */
934             modify_size   = False;
935             modify_tocptr = False;
936             old_size   = 0;
937 
938             if (prev->from_opd && !from_opd
939                 && (prev->size == 24 || prev->size == 16)
940                 && sym_size != prev->size) {
941                /* Existing one is an opd-redirect, with a bogus size,
942                   so the only useful new fact we have is the real size
943                   of the symbol. */
944                modify_size = True;
945                old_size = prev->size;
946                prev->size = sym_size;
947             }
948             else
949             if (!prev->from_opd && from_opd
950                 && (sym_size == 24 || sym_size == 16)) {
951                /* Existing one is non-opd, new one is opd.  What we
952                   can acquire from the new one is the TOC ptr to be
953                   used.  Since the existing sym is non-toc, it
954                   shouldn't currently have an known TOC ptr. */
955                vg_assert(prev->tocptr == 0);
956                modify_tocptr = True;
957                prev->tocptr = GET_TOCPTR_AVMA(sym_avmas_really);
958             }
959             else {
960                /* ignore. can we do better here? */
961             }
962 
963             /* Only one or the other is possible (I think) */
964             vg_assert(!(modify_size && modify_tocptr));
965 
966             if (modify_size && di->trace_symtab) {
967                VG_(printf)("    modify (old sz %4d)    "
968                            " val %#010lx, toc %#010lx, sz %4d  %lld\n",
969                            old_size,
970                            prev->key.addr,
971                            prev->tocptr,
972                            (Int)  prev->size,
973                            (ULong)prev->key.name
974                );
975             }
976             if (modify_tocptr && di->trace_symtab) {
977                VG_(printf)("    modify (upd tocptr)     "
978                            " val %#010lx, toc %#010lx, sz %4d  %lld\n",
979                            prev->key.addr,
980                            prev->tocptr,
981                            (Int)  prev->size,
982                            (ULong)prev->key.name
983                );
984             }
985 
986          } else {
987 
988             /* A new (name,addr) key.  Add and continue. */
989             elem = VG_(OSetGen_AllocNode)(oset, sizeof(TempSym));
990             elem->key      = key;
991             elem->tocptr   = GET_TOCPTR_AVMA(sym_avmas_really);
992             elem->size     = sym_size;
993             elem->from_opd = from_opd;
994             elem->is_text  = is_text;
995             elem->is_ifunc = is_ifunc;
996             VG_(OSetGen_Insert)(oset, elem);
997             if (di->trace_symtab) {
998                HChar* str = ML_(img_strdup)(escn_strtab->img, "di.respl.2",
999                                             elem->key.name);
1000                VG_(printf)("   to-oset [%4ld]:          "
1001                            "  val %#010lx, toc %#010lx, sz %4d  %s\n",
1002                            i,
1003                            elem->key.addr,
1004                            elem->tocptr,
1005                            (Int)  elem->size,
1006                            str
1007                );
1008                if (str) ML_(dinfo_free)(str);
1009             }
1010 
1011          }
1012       }
1013    }
1014 
1015    /* All the syms that matter are in the oset.  Now pull them out,
1016       build a "standard" symbol table, and nuke the oset. */
1017 
1018    i = 0;
1019    VG_(OSetGen_ResetIter)( oset );
1020 
1021    while ( (elem = VG_(OSetGen_Next)(oset)) ) {
1022       DiSym disym;
1023       VG_(memset)(&disym, 0, sizeof(disym));
1024       HChar* cstr = ML_(img_strdup)(escn_strtab->img,
1025                                     "di.res__ppc64.1", elem->key.name);
1026       disym.avmas.main = elem->key.addr;
1027       SET_TOCPTR_AVMA(disym.avmas, elem->tocptr);
1028       SET_LOCAL_EP_AVMA(disym.avmas, 0); // ppc64be does not use local_ep.
1029       disym.pri_name  = ML_(addStr) ( di, cstr, -1 );
1030       disym.sec_names = NULL;
1031       disym.size      = elem->size;
1032       disym.isText    = elem->is_text;
1033       disym.isIFunc   = elem->is_ifunc;
1034       if (cstr) { ML_(dinfo_free)(cstr); cstr = NULL; }
1035       vg_assert(disym.pri_name != NULL);
1036 
1037       ML_(addSym) ( di, &disym );
1038       if (di->trace_symtab) {
1039          VG_(printf)("    rec(%c) [%4ld]:          "
1040                      "   val %#010lx, toc %#010lx, sz %4d  %s\n",
1041                      disym.isText ? 't' : 'd',
1042                      i,
1043                      disym.avmas.main,
1044                      GET_TOCPTR_AVMA(disym.avmas),
1045                      (Int)   disym.size,
1046                      disym.pri_name
1047                );
1048       }
1049       i++;
1050    }
1051 
1052    VG_(OSetGen_Destroy)( oset );
1053 }
1054 
1055 
1056 /*
1057  * Look for a build-id in an ELF image. The build-id specification
1058  * can be found here:
1059  *
1060  * http://fedoraproject.org/wiki/RolandMcGrath/BuildID
1061  *
1062  * Returned string must be freed by the caller.
1063  */
1064 static
find_buildid(DiImage * img,Bool rel_ok,Bool search_shdrs)1065 HChar* find_buildid(DiImage* img, Bool rel_ok, Bool search_shdrs)
1066 {
1067    HChar* buildid = NULL;
1068 
1069 #  ifdef NT_GNU_BUILD_ID
1070    if (is_elf_object_file_by_DiImage(img, rel_ok)) {
1071       Word i;
1072 
1073       ElfXX_Ehdr ehdr;
1074       ML_(img_get)(&ehdr, img, 0, sizeof(ehdr));
1075       for (i = 0; i < ehdr.e_phnum; i++) {
1076          ElfXX_Phdr phdr;
1077          ML_(img_get)(&phdr, img,
1078                       ehdr.e_phoff + i * ehdr.e_phentsize, sizeof(phdr));
1079 
1080          if (phdr.p_type == PT_NOTE) {
1081             ElfXX_Off note_ioff = phdr.p_offset;
1082 
1083             while (note_ioff < phdr.p_offset + phdr.p_filesz) {
1084                ElfXX_Nhdr note;
1085                ML_(img_get)(&note, img, (DiOffT)note_ioff, sizeof(note));
1086                DiOffT name_ioff = note_ioff + sizeof(ElfXX_Nhdr);
1087                DiOffT desc_ioff = name_ioff + ((note.n_namesz + 3) & ~3);
1088                if (ML_(img_strcmp_c)(img, name_ioff, ELF_NOTE_GNU) == 0
1089                    && note.n_type == NT_GNU_BUILD_ID) {
1090                   buildid = ML_(dinfo_zalloc)("di.fbi.1",
1091                                               note.n_descsz * 2 + 1);
1092                   Word j;
1093                   for (j = 0; j < note.n_descsz; j++) {
1094                      UChar desc_j = ML_(img_get_UChar)(img, desc_ioff + j);
1095                      VG_(sprintf)(buildid + VG_(strlen)(buildid),
1096                                   "%02x", (UInt)desc_j);
1097                   }
1098                }
1099 
1100                note_ioff = note_ioff + sizeof(ElfXX_Nhdr)
1101                                      + ((note.n_namesz + 3) & ~3)
1102                                      + ((note.n_descsz + 3) & ~3);
1103             }
1104          }
1105       }
1106 
1107       /* Normally we would only search shdrs for ET_REL files, but when
1108          we search for a separate .debug file phdrs might not be there
1109          (they are never loaded) or have been corrupted, so try again
1110          against shdrs. */
1111       if (buildid || (!rel_ok && !search_shdrs))
1112          return buildid;
1113 
1114       for (i = 0; i < ehdr.e_shnum; i++) {
1115          ElfXX_Shdr shdr;
1116          ML_(img_get)(&shdr, img,
1117                       ehdr.e_shoff + i * ehdr.e_shentsize, sizeof(shdr));
1118 
1119          if (shdr.sh_type == SHT_NOTE) {
1120             ElfXX_Off note_ioff = shdr.sh_offset;
1121 
1122             while (note_ioff < shdr.sh_offset + shdr.sh_size) {
1123                ElfXX_Nhdr note;
1124                ML_(img_get)(&note, img, (DiOffT)note_ioff, sizeof(note));
1125                DiOffT name_ioff = note_ioff + sizeof(ElfXX_Nhdr);
1126                DiOffT desc_ioff = name_ioff + ((note.n_namesz + 3) & ~3);
1127 
1128                if (ML_(img_strcmp_c)(img, name_ioff, ELF_NOTE_GNU) == 0
1129                    && note.n_type == NT_GNU_BUILD_ID) {
1130                   buildid = ML_(dinfo_zalloc)("di.fbi.2",
1131                                               note.n_descsz * 2 + 1);
1132                   Word j;
1133                   for (j = 0; j < note.n_descsz; j++) {
1134                      UChar desc_j = ML_(img_get_UChar)(img, desc_ioff + j);
1135                      VG_(sprintf)(buildid + VG_(strlen)(buildid),
1136                                   "%02x", (UInt)desc_j);
1137                   }
1138                }
1139 
1140                note_ioff = note_ioff + sizeof(ElfXX_Nhdr)
1141                                      + ((note.n_namesz + 3) & ~3)
1142                                      + ((note.n_descsz + 3) & ~3);
1143             }
1144          }
1145       }
1146    }
1147 #  endif /* def NT_GNU_BUILD_ID */
1148 
1149    return buildid;
1150 }
1151 
1152 
1153 /* Try and open a separate debug file, ignoring any where the CRC does
1154    not match the value from the main object file.  Returned DiImage
1155    must be discarded by the caller.
1156 
1157    If |serverAddr| is NULL, |name| is expected to be a fully qualified
1158    (absolute) path to the file in the local filesystem.  If
1159    |serverAddr| is non-NULL, it is expected to be an IPv4 and port
1160    spec of the form "d.d.d.d:d" or "d.d.d.d", and |name| is expected
1161    to be a plain filename (no path components at all).
1162  */
1163 static
open_debug_file(const HChar * name,const HChar * buildid,UInt crc,Bool rel_ok,const HChar * serverAddr)1164 DiImage* open_debug_file( const HChar* name, const HChar* buildid, UInt crc,
1165                           Bool rel_ok, const HChar* serverAddr )
1166 {
1167    DiImage* dimg
1168      = serverAddr ? ML_(img_from_di_server)(name, serverAddr)
1169                   : ML_(img_from_local_file)(name);
1170    if (dimg == NULL)
1171       return NULL;
1172 
1173    if (VG_(clo_verbosity) > 1) {
1174       if (serverAddr)
1175          VG_(message)(Vg_DebugMsg, "  Considering %s on server %s ..\n",
1176                                    name, serverAddr);
1177       else
1178          VG_(message)(Vg_DebugMsg, "  Considering %s ..\n", name);
1179    }
1180 
1181    /* We will always check the crc if we have one (altfiles don't have one)
1182       for now because we might be opening the main file again by any other
1183       name, and that obviously also has the same buildid. More efficient
1184       would be an fstat bases check or a check that the file actually
1185       contains .debug* sections. */
1186    if (buildid && crc == 0) {
1187       HChar* debug_buildid = find_buildid(dimg, rel_ok, True);
1188       if (debug_buildid == NULL || VG_(strcmp)(buildid, debug_buildid) != 0) {
1189          ML_(img_done)(dimg);
1190          if (VG_(clo_verbosity) > 1)
1191             VG_(message)(Vg_DebugMsg,
1192                "  .. build-id mismatch (found %s wanted %s)\n",
1193                debug_buildid, buildid);
1194          ML_(dinfo_free)(debug_buildid);
1195          return NULL;
1196       }
1197       ML_(dinfo_free)(debug_buildid);
1198       if (VG_(clo_verbosity) > 1)
1199          VG_(message)(Vg_DebugMsg, "  .. build-id is valid\n");
1200    } else {
1201       UInt calccrc = ML_(img_calc_gnu_debuglink_crc32)(dimg);
1202       if (calccrc != crc) {
1203          ML_(img_done)(dimg);
1204          if (VG_(clo_verbosity) > 1)
1205             VG_(message)(Vg_DebugMsg,
1206                "  .. CRC mismatch (computed %08x wanted %08x)\n", calccrc, crc);
1207          return NULL;
1208       }
1209 
1210       if (VG_(clo_verbosity) > 1)
1211          VG_(message)(Vg_DebugMsg, "  .. CRC is valid\n");
1212    }
1213 
1214    return dimg;
1215 }
1216 
1217 
1218 /* Try to find a separate debug file for a given object file.  If
1219    found, return its DiImage, which should be freed by the caller.  If
1220    |buildid| is non-NULL, then a debug object matching it is
1221    acceptable.  If |buildid| is NULL or doesn't specify a findable
1222    debug object, then we look in various places to find a file with
1223    the specified CRC.  And if that doesn't work out then we give
1224    up. */
1225 static
find_debug_file(struct _DebugInfo * di,const HChar * objpath,const HChar * buildid,const HChar * debugname,UInt crc,Bool rel_ok)1226 DiImage* find_debug_file( struct _DebugInfo* di,
1227                           const HChar* objpath, const HChar* buildid,
1228                           const HChar* debugname, UInt crc, Bool rel_ok )
1229 {
1230    const HChar* extrapath  = VG_(clo_extra_debuginfo_path);
1231    const HChar* serverpath = VG_(clo_debuginfo_server);
1232 
1233    DiImage* dimg      = NULL; /* the img that we found */
1234    HChar*   debugpath = NULL; /* where we found it */
1235 
1236    if (buildid != NULL) {
1237       debugpath = ML_(dinfo_zalloc)("di.fdf.1",
1238                                     VG_(strlen)(buildid) + 33);
1239 
1240       VG_(sprintf)(debugpath, "/usr/lib/debug/.build-id/%c%c/%s.debug",
1241                    buildid[0], buildid[1], buildid + 2);
1242 
1243       dimg = open_debug_file(debugpath, buildid, 0, rel_ok, NULL);
1244       if (!dimg) {
1245          ML_(dinfo_free)(debugpath);
1246          debugpath = NULL;
1247       }
1248    }
1249 
1250    if (dimg == NULL && debugname != NULL) {
1251       HChar *objdir = ML_(dinfo_strdup)("di.fdf.2", objpath);
1252       HChar *objdirptr;
1253 
1254       if ((objdirptr = VG_(strrchr)(objdir, '/')) != NULL)
1255          *objdirptr = '\0';
1256 
1257       debugpath = ML_(dinfo_zalloc)(
1258                      "di.fdf.3",
1259                      VG_(strlen)(objdir) + VG_(strlen)(debugname) + 64
1260                      + (extrapath ? VG_(strlen)(extrapath) : 0)
1261                      + (serverpath ? VG_(strlen)(serverpath) : 0));
1262 
1263       VG_(sprintf)(debugpath, "%s/%s", objdir, debugname);
1264       dimg = open_debug_file(debugpath, buildid, crc, rel_ok, NULL);
1265       if (dimg != NULL) goto dimg_ok;
1266 
1267       VG_(sprintf)(debugpath, "%s/.debug/%s", objdir, debugname);
1268       dimg = open_debug_file(debugpath, buildid, crc, rel_ok, NULL);
1269       if (dimg != NULL) goto dimg_ok;
1270 
1271       VG_(sprintf)(debugpath, "/usr/lib/debug%s/%s", objdir, debugname);
1272       dimg = open_debug_file(debugpath, buildid, crc, rel_ok, NULL);
1273       if (dimg != NULL) goto dimg_ok;
1274 
1275       if (extrapath) {
1276          VG_(sprintf)(debugpath, "%s%s/%s", extrapath,
1277                                             objdir, debugname);
1278          dimg = open_debug_file(debugpath, buildid, crc, rel_ok, NULL);
1279          if (dimg != NULL) goto dimg_ok;
1280       }
1281 
1282       if (serverpath) {
1283          /* When looking on the debuginfo server, always just pass the
1284             basename. */
1285          const HChar* basename = debugname;
1286          if (VG_(strstr)(basename, "/") != NULL) {
1287             basename = VG_(strrchr)(basename, '/') + 1;
1288          }
1289          VG_(sprintf)(debugpath, "%s on %s", basename, serverpath);
1290          dimg = open_debug_file(basename, buildid, crc, rel_ok, serverpath);
1291          if (dimg) goto dimg_ok;
1292       }
1293 
1294       dimg_ok:
1295 
1296       ML_(dinfo_free)(objdir);
1297    }
1298 
1299    if (dimg != NULL) {
1300       vg_assert(debugpath);
1301       TRACE_SYMTAB("\n");
1302       TRACE_SYMTAB("------ Found a debuginfo file: %s\n", debugpath);
1303 
1304       /* Only set once, we might be called again for opening the altfile. */
1305       if (di->fsm.dbgname == NULL)
1306          di->fsm.dbgname = ML_(dinfo_strdup)("di.fdf.4", debugpath);
1307    }
1308 
1309    if (debugpath)
1310       ML_(dinfo_free)(debugpath);
1311 
1312    return dimg;
1313 }
1314 
1315 
1316 /* Try to find a separate debug file for a given object file, in a
1317    hacky and dangerous way: check only the --extra-debuginfo-path and
1318    the --debuginfo-server.  And don't do a consistency check. */
1319 static
find_debug_file_ad_hoc(const DebugInfo * di,const HChar * objpath)1320 DiImage* find_debug_file_ad_hoc( const DebugInfo* di,
1321                                  const HChar* objpath )
1322 {
1323    const HChar* extrapath  = VG_(clo_extra_debuginfo_path);
1324    const HChar* serverpath = VG_(clo_debuginfo_server);
1325 
1326    DiImage* dimg      = NULL; /* the img that we found */
1327    HChar*   debugpath = NULL; /* where we found it */
1328 
1329    HChar *objdir = ML_(dinfo_strdup)("di.fdfah.1", objpath);
1330    HChar *objdirptr;
1331 
1332    if ((objdirptr = VG_(strrchr)(objdir, '/')) != NULL)
1333       *objdirptr = '\0';
1334 
1335    debugpath = ML_(dinfo_zalloc)(
1336                   "di.fdfah.3",
1337                   VG_(strlen)(objdir) + 64
1338                   + (extrapath ? VG_(strlen)(extrapath) : 0)
1339                   + (serverpath ? VG_(strlen)(serverpath) : 0));
1340 
1341    if (extrapath) {
1342       VG_(sprintf)(debugpath, "%s/%s", extrapath, objpath);
1343       dimg = ML_(img_from_local_file)(debugpath);
1344       if (dimg != NULL) {
1345          if (VG_(clo_verbosity) > 1) {
1346             VG_(message)(Vg_DebugMsg, "  Using (POSSIBLY MISMATCHED) %s\n",
1347                                       debugpath);
1348          }
1349          goto dimg_ok;
1350       }
1351    }
1352    if (serverpath) {
1353       /* When looking on the debuginfo server, always just pass the
1354          basename. */
1355       const HChar* basename = objpath;
1356       if (VG_(strstr)(basename, "/") != NULL) {
1357          basename = VG_(strrchr)(basename, '/') + 1;
1358       }
1359       VG_(sprintf)(debugpath, "%s on %s", basename, serverpath);
1360       dimg = ML_(img_from_di_server)(basename, serverpath);
1361       if (dimg != NULL) {
1362          if (VG_(clo_verbosity) > 1) {
1363             VG_(message)(Vg_DebugMsg, "  Using (POSSIBLY MISMATCHED) %s\n",
1364                                       debugpath);
1365          }
1366          goto dimg_ok;
1367       }
1368    }
1369 
1370    dimg_ok:
1371 
1372    ML_(dinfo_free)(objdir);
1373 
1374    if (dimg != NULL) {
1375       vg_assert(debugpath);
1376       TRACE_SYMTAB("\n");
1377       TRACE_SYMTAB("------ Found an ad_hoc debuginfo file: %s\n", debugpath);
1378    }
1379 
1380    if (debugpath)
1381       ML_(dinfo_free)(debugpath);
1382 
1383    return dimg;
1384 }
1385 
1386 
INDEX_BIS(DiOffT base,UWord idx,UWord scale)1387 static DiOffT INDEX_BIS ( DiOffT base, UWord idx, UWord scale ) {
1388    // This is a bit stupid.  Really, idx and scale ought to be
1389    // 64-bit quantities, always.
1390    return base + (DiOffT)idx * (DiOffT)scale;
1391 }
1392 
1393 
1394 /* Find the file offset corresponding to SVMA by using the program
1395    headers.  This is taken from binutils-2.17/binutils/readelf.c
1396    offset_from_vma(). */
1397 static
file_offset_from_svma(Bool * ok,Addr svma,DiImage * img,DiOffT phdr_ioff,Word phdr_nent,Word phdr_ent_szB)1398 Word file_offset_from_svma ( /*OUT*/Bool* ok,
1399                              Addr         svma,
1400                              DiImage*     img,
1401                              DiOffT       phdr_ioff,
1402                              Word         phdr_nent,
1403                              Word         phdr_ent_szB )
1404 {
1405    Word i;
1406    for (i = 0; i < phdr_nent; i++) {
1407       ElfXX_Phdr seg;
1408       ML_(img_get)(&seg, img,
1409                    INDEX_BIS(phdr_ioff, i, phdr_ent_szB), sizeof(seg));
1410       if (seg.p_type != PT_LOAD)
1411          continue;
1412       if (svma >= (seg.p_vaddr & -seg.p_align)
1413           && svma + 1 <= seg.p_vaddr + seg.p_filesz) {
1414          *ok = True;
1415          return svma - seg.p_vaddr + seg.p_offset;
1416       }
1417    }
1418    *ok = False;
1419    return 0;
1420 }
1421 
1422 
1423 /* The central function for reading ELF debug info.  For the
1424    object/exe specified by the DebugInfo, find ELF sections, then read
1425    the symbols, line number info, file name info, CFA (stack-unwind
1426    info) and anything else we want, into the tables within the
1427    supplied DebugInfo.
1428 */
1429 
ML_(read_elf_debug_info)1430 Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di )
1431 {
1432    /* This function is long and complex.  That, and the presence of
1433       nested scopes, means it's not always easy to see which parts are
1434       in loops/conditionals and which aren't.  To make it easier to
1435       follow, points executed exactly once -- that is, those which are
1436       the top level of the function -- are marked TOPLEVEL.
1437    */
1438    /* Consistent terminology for local variable names, without which
1439       it's almost unfollowably complex:
1440 
1441       In which file?
1442          in the main ELF file         *_m*
1443          in the debuginfo file        *_d*
1444          in the alt debuginfo file    *_a*
1445 
1446       What kind of thing?
1447          _{m,d,a}img       a DiImage*
1448          _{m,d,a}ioff      an offset in the image (DiOffT)
1449          _{m,d,a}nent      "number of entries"
1450          _{m,d,a}ent_szB   "size in bytes of an entry"
1451          ehdr_{m,d,a}      ELF header
1452          phdr              Program header
1453          shdr              Section header
1454          a_X               a temporary X
1455          _escn             an DiSlice (elf section info) variable
1456          szB               size in bytes
1457    */
1458 
1459 
1460    /* TOPLEVEL */
1461    Bool     res, ok;
1462    Word     i, j;
1463    Bool     dynbss_present = False;
1464    Bool     sdynbss_present = False;
1465 
1466    /* Image for the main ELF file we're working with. */
1467    DiImage* mimg = NULL;
1468 
1469    /* Ditto for any ELF debuginfo file that we might happen to load. */
1470    DiImage* dimg = NULL;
1471 
1472    /* Ditto for alternate ELF debuginfo file that we might happen to load. */
1473    DiImage* aimg = NULL;
1474 
1475    /* ELF header offset for the main file.  Should be zero since the
1476       ELF header is at start of file. */
1477    DiOffT   ehdr_mioff = 0;
1478 
1479    /* Program header table image addr, # entries, entry size */
1480    DiOffT   phdr_mioff    = 0;
1481    UWord    phdr_mnent    = 0;
1482    UWord    phdr_ment_szB = 0;
1483 
1484    /* Section header image addr, # entries, entry size.  Also the
1485       associated string table. */
1486    DiOffT   shdr_mioff        = 0;
1487    UWord    shdr_mnent        = 0;
1488    UWord    shdr_ment_szB     = 0;
1489    DiOffT   shdr_strtab_mioff = 0;
1490 
1491    /* SVMAs covered by rx and rw segments and corresponding biases.
1492       Normally each object would provide just one rx and one rw area,
1493       but various ELF mangling tools create objects with multiple
1494       such entries, hence the generality. */
1495    typedef
1496       struct {
1497          Addr     svma_base;
1498          Addr     svma_limit;
1499          PtrdiffT bias;
1500          Bool     exec;
1501       }
1502       RangeAndBias;
1503 
1504    XArray* /* of RangeAndBias */ svma_ranges = NULL;
1505 
1506    vg_assert(di);
1507    vg_assert(di->fsm.have_rx_map == True);
1508    vg_assert(di->fsm.have_rw_map == True);
1509    vg_assert(di->have_dinfo == False);
1510    vg_assert(di->fsm.filename);
1511    vg_assert(!di->symtab);
1512    vg_assert(!di->loctab);
1513    vg_assert(!di->inltab);
1514    vg_assert(!di->cfsi_base);
1515    vg_assert(!di->cfsi_m_ix);
1516    vg_assert(!di->cfsi_rd);
1517    vg_assert(!di->cfsi_exprs);
1518    vg_assert(!di->strpool);
1519    vg_assert(!di->fndnpool);
1520    vg_assert(!di->soname);
1521 
1522    {
1523       Bool has_nonempty_rx = False;
1524       Bool has_nonempty_rw = False;
1525       for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
1526          DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
1527          if (!map->rx && !map->rw)
1528             continue;
1529          if (map->rx && map->size > 0)
1530             has_nonempty_rx = True;
1531          if (map->rw && map->size > 0)
1532             has_nonempty_rw = True;
1533          /* If this doesn't hold true, it means that m_syswrap/m_aspacemgr
1534             managed to do a mapping where the start isn't page aligned.
1535             Which sounds pretty bogus to me. */
1536          vg_assert(VG_IS_PAGE_ALIGNED(map->avma));
1537       }
1538       vg_assert(has_nonempty_rx);
1539       vg_assert(has_nonempty_rw);
1540    }
1541 
1542    /* ----------------------------------------------------------
1543       At this point, there is very little information in the
1544       DebugInfo.  We only know that something that looks like an ELF
1545       file has been mapped rx-ishly and rw-ishly as recorded in the
1546       di->fsm.maps array items.  First we examine the file's ELF
1547       Program Header, and, by comparing that against the di->fsm.maps
1548       info, try to figure out the AVMAs for the sections we care
1549       about, that should have been mapped: text, data, sdata, bss,
1550       got, plt, and toc.
1551       ---------------------------------------------------------- */
1552 
1553    res = False;
1554 
1555    if (VG_(clo_verbosity) > 1 || VG_(clo_trace_redir))
1556       VG_(message)(Vg_DebugMsg, "Reading syms from %s\n",
1557                                 di->fsm.filename );
1558 
1559    /* Connect to the primary object image, so that we can read symbols
1560       and line number info out of it.  It will be disconnected
1561       immediately thereafter; it is only connected transiently. */
1562    mimg = ML_(img_from_local_file)(di->fsm.filename);
1563    if (mimg == NULL) {
1564       VG_(message)(Vg_UserMsg, "warning: connection to image %s failed\n",
1565                                di->fsm.filename );
1566       VG_(message)(Vg_UserMsg, "         no symbols or debug info loaded\n" );
1567       return False;
1568    }
1569 
1570    /* Ok, the object image is available.  Now verify that it is a
1571       valid ELF .so or executable image. */
1572    ok = is_elf_object_file_by_DiImage(mimg, False);
1573    if (!ok) {
1574       ML_(symerr)(di, True, "Invalid ELF Header");
1575       goto out;
1576    }
1577 
1578    /* Find where the program and section header tables are, and give
1579       up if either is missing or outside the image (bogus). */
1580    ElfXX_Ehdr ehdr_m;
1581    vg_assert(ehdr_mioff == 0); // ensured by its initialisation
1582    ok = ML_(img_valid)(mimg, ehdr_mioff, sizeof(ehdr_m));
1583    vg_assert(ok); // ML_(is_elf_object_file) should ensure this
1584    ML_(img_get)(&ehdr_m, mimg, ehdr_mioff, sizeof(ehdr_m));
1585 
1586    phdr_mioff    = ehdr_mioff + ehdr_m.e_phoff;
1587    phdr_mnent    = ehdr_m.e_phnum;
1588    phdr_ment_szB = ehdr_m.e_phentsize;
1589 
1590    shdr_mioff    = ehdr_mioff + ehdr_m.e_shoff;
1591    shdr_mnent    = ehdr_m.e_shnum;
1592    shdr_ment_szB = ehdr_m.e_shentsize;
1593 
1594    TRACE_SYMTAB("------ Basic facts about the object ------\n");
1595    TRACE_SYMTAB("object:  n_oimage %llu\n",
1596                 (ULong)ML_(img_size)(mimg));
1597    TRACE_SYMTAB("phdr:    ioff %llu nent %ld ent_szB %ld\n",
1598                phdr_mioff, phdr_mnent, phdr_ment_szB);
1599    TRACE_SYMTAB("shdr:    ioff %llu nent %ld ent_szB %ld\n",
1600                shdr_mioff, shdr_mnent, shdr_ment_szB);
1601    for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
1602       const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
1603       if (map->rx)
1604          TRACE_SYMTAB("rx_map:  avma %#lx   size %lu  foff %lu\n",
1605                       map->avma, map->size, map->foff);
1606    }
1607    for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
1608       const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
1609       if (map->rw)
1610          TRACE_SYMTAB("rw_map:  avma %#lx   size %lu  foff %lu\n",
1611                       map->avma, map->size, map->foff);
1612    }
1613 
1614    if (phdr_mnent == 0
1615        || !ML_(img_valid)(mimg, phdr_mioff, phdr_mnent * phdr_ment_szB)) {
1616       ML_(symerr)(di, True, "Missing or invalid ELF Program Header Table");
1617       goto out;
1618    }
1619 
1620    if (shdr_mnent == 0
1621        || !ML_(img_valid)(mimg, shdr_mioff, shdr_mnent * shdr_ment_szB)) {
1622       ML_(symerr)(di, True, "Missing or invalid ELF Section Header Table");
1623       goto out;
1624    }
1625 
1626    /* Also find the section header's string table, and validate. */
1627    /* checked previously by is_elf_object_file: */
1628    vg_assert(ehdr_m.e_shstrndx != SHN_UNDEF);
1629 
1630    // shdr_mioff is the offset of the section header table
1631    // and we need the ehdr_m.e_shstrndx'th entry
1632    { ElfXX_Shdr a_shdr;
1633      ML_(img_get)(&a_shdr, mimg,
1634                   INDEX_BIS(shdr_mioff, ehdr_m.e_shstrndx, shdr_ment_szB),
1635                   sizeof(a_shdr));
1636      shdr_strtab_mioff
1637         = ehdr_mioff /* isn't this always zero? */ + a_shdr.sh_offset;
1638 
1639      if (!ML_(img_valid)(mimg, shdr_strtab_mioff,
1640                          1/*bogus, but we don't know the real size*/ )) {
1641         ML_(symerr)(di, True, "Invalid ELF Section Header String Table");
1642         goto out;
1643      }
1644    }
1645 
1646    TRACE_SYMTAB("shdr:    string table at %llu\n", shdr_strtab_mioff);
1647 
1648    svma_ranges = VG_(newXA)(ML_(dinfo_zalloc), "di.relfdi.1",
1649                             ML_(dinfo_free), sizeof(RangeAndBias));
1650 
1651    /* TOPLEVEL */
1652    /* Look through the program header table, and:
1653       - copy information from suitable PT_LOAD entries into svma_ranges
1654       - find (or fake up) the .soname for this object.
1655    */
1656    TRACE_SYMTAB("\n");
1657    TRACE_SYMTAB("------ Examining the program headers ------\n");
1658    vg_assert(di->soname == NULL);
1659    {
1660       /* TOPLEVEL */
1661       ElfXX_Addr prev_svma = 0;
1662 
1663       for (i = 0; i < phdr_mnent; i++) {
1664          ElfXX_Phdr a_phdr;
1665          ML_(img_get)(&a_phdr, mimg,
1666                       INDEX_BIS(phdr_mioff, i, phdr_ment_szB),
1667                       sizeof(a_phdr));
1668 
1669          /* Make sure the PT_LOADable entries are in order and
1670             non-overlapping.  This in turn means the address ranges
1671             slurped into svma_ranges are in order and
1672             non-overlapping. */
1673 
1674          if (a_phdr.p_type == PT_LOAD) {
1675             TRACE_SYMTAB("PT_LOAD[%ld]: p_vaddr %#lx (prev %#lx)\n",
1676                          i, (UWord)a_phdr.p_vaddr, (UWord)prev_svma);
1677             TRACE_SYMTAB("PT_LOAD[%ld]:   p_offset %lu, p_filesz %lu,"
1678                          " perms %c%c%c\n",
1679                          i, (UWord)a_phdr.p_offset, (UWord)a_phdr.p_filesz,
1680                          a_phdr.p_flags & PF_R ? 'r' : '-',
1681                          a_phdr.p_flags & PF_W ? 'w' : '-',
1682                          a_phdr.p_flags & PF_X ? 'x' : '-');
1683             if (a_phdr.p_vaddr < prev_svma) {
1684                ML_(symerr)(di, True,
1685                            "ELF Program Headers are not in ascending order");
1686                goto out;
1687             }
1688             prev_svma = a_phdr.p_vaddr;
1689             if (a_phdr.p_memsz > 0) {
1690                Bool loaded = False;
1691                for (j = 0; j < VG_(sizeXA)(di->fsm.maps); j++) {
1692                   const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, j);
1693                   if (   (map->rx || map->rw)
1694                       && map->size > 0 /* stay sane */
1695                       && a_phdr.p_offset >= map->foff
1696                       && a_phdr.p_offset <  map->foff + map->size
1697                       && a_phdr.p_offset + a_phdr.p_filesz
1698                          <= map->foff + map->size) {
1699                      RangeAndBias item;
1700                      item.svma_base  = a_phdr.p_vaddr;
1701                      item.svma_limit = a_phdr.p_vaddr + a_phdr.p_memsz;
1702                      item.bias       = map->avma - map->foff
1703                                        + a_phdr.p_offset - a_phdr.p_vaddr;
1704                      if (map->rw
1705                          && (a_phdr.p_flags & (PF_R | PF_W))
1706                             == (PF_R | PF_W)) {
1707                         item.exec = False;
1708                         VG_(addToXA)(svma_ranges, &item);
1709                         TRACE_SYMTAB(
1710                            "PT_LOAD[%ld]:   acquired as rw, bias 0x%lx\n",
1711                            i, item.bias);
1712                         loaded = True;
1713                      }
1714                      if (map->rx
1715                          && (a_phdr.p_flags & (PF_R | PF_X))
1716                             == (PF_R | PF_X)) {
1717                         item.exec = True;
1718                         VG_(addToXA)(svma_ranges, &item);
1719                         TRACE_SYMTAB(
1720                            "PT_LOAD[%ld]:   acquired as rx, bias 0x%lx\n",
1721                            i, item.bias);
1722                         loaded = True;
1723                      }
1724                   }
1725                }
1726                if (!loaded) {
1727                   ML_(symerr)(di, False,
1728                               "ELF section outside all mapped regions");
1729                   /* This problem might be solved by further memory mappings.
1730                      Avoid the vg_assert(!di->soname) at the beginning of this
1731                      function if DYNAMIC section has been already processed. */
1732                   if (di->soname) {
1733                      ML_(dinfo_free)(di->soname);
1734                      di->soname = NULL;
1735                   }
1736                   goto out;
1737                }
1738             }
1739          }
1740 
1741          /* Try to get the soname.  If there isn't one, use "NONE".
1742             The seginfo needs to have some kind of soname in order to
1743             facilitate writing redirect functions, since all redirect
1744             specifications require a soname (pattern). */
1745          if (a_phdr.p_type == PT_DYNAMIC && di->soname == NULL) {
1746             Word   stroff       = -1;
1747             DiOffT strtab_mioff = DiOffT_INVALID;
1748             for (j = 0; True/*exit check is in the loop*/; j++) {
1749                ElfXX_Dyn t_dyn_m; /* dyn_img[j] */
1750                ML_(img_get)(&t_dyn_m, mimg,
1751                             INDEX_BIS(ehdr_mioff + a_phdr.p_offset,
1752                                       j, sizeof(ElfXX_Dyn)),
1753                             sizeof(t_dyn_m));
1754                if (t_dyn_m.d_tag == DT_NULL)
1755                   break;
1756 
1757                switch (t_dyn_m.d_tag) {
1758                   case DT_SONAME: {
1759                      stroff = t_dyn_m.d_un.d_val;
1760                      break;
1761                   }
1762                   case DT_STRTAB: {
1763                      Bool ok2 = False;
1764                      Word offset = file_offset_from_svma(
1765                                       &ok2, t_dyn_m.d_un.d_ptr, mimg,
1766                                       phdr_mioff, phdr_mnent, phdr_ment_szB
1767                                    );
1768                      if (ok2 && strtab_mioff == DiOffT_INVALID) {
1769                         // Check for obviously bogus offsets.
1770                         if (!ML_(img_valid)(mimg, offset, 1)) {
1771                            ML_(symerr)(di, True, "Invalid DT_STRTAB offset");
1772                            goto out;
1773                         }
1774                         strtab_mioff = ehdr_mioff + offset;
1775                         vg_assert(ehdr_mioff == 0); // should always be
1776                      }
1777                      break;
1778                   }
1779                   default:
1780                      break;
1781                }
1782             }
1783             if (stroff != -1 && strtab_mioff != DiOffT_INVALID) {
1784                di->soname = ML_(img_strdup)(mimg, "di.redi.1",
1785                                             strtab_mioff + stroff);
1786                TRACE_SYMTAB("Found soname = %s\n", di->soname);
1787             }
1788          }
1789       } /* for (i = 0; i < phdr_Mnent; i++) ... */
1790       /* TOPLEVEL */
1791 
1792    } /* examine the program headers (local scope) */
1793 
1794    /* TOPLEVEL */
1795 
1796    /* If, after looking at all the program headers, we still didn't
1797       find a soname, add a fake one. */
1798    if (di->soname == NULL) {
1799       TRACE_SYMTAB("No soname found; using (fake) \"NONE\"\n");
1800       di->soname = ML_(dinfo_strdup)("di.redi.2", "NONE");
1801    }
1802 
1803    vg_assert(VG_(sizeXA)(svma_ranges) != 0);
1804 
1805    /* Now read the section table. */
1806    TRACE_SYMTAB("\n");
1807    TRACE_SYMTAB("------ Examining the section headers ------\n");
1808    for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
1809       const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
1810       if (map->rx)
1811          TRACE_SYMTAB("rx: at %#lx are mapped foffsets %ld .. %ld\n",
1812                       map->avma, map->foff, map->foff + map->size - 1 );
1813    }
1814    TRACE_SYMTAB("rx: contains these svma regions:\n");
1815    for (i = 0; i < VG_(sizeXA)(svma_ranges); i++) {
1816       const RangeAndBias* reg = VG_(indexXA)(svma_ranges, i);
1817       if (reg->exec)
1818          TRACE_SYMTAB("  svmas %#lx .. %#lx with bias %#lx\n",
1819                       reg->svma_base, reg->svma_limit - 1, reg->bias );
1820    }
1821    for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
1822       const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
1823       if (map->rw)
1824          TRACE_SYMTAB("rw: at %#lx are mapped foffsets %ld .. %ld\n",
1825                       map->avma, map->foff, map->foff + map->size - 1 );
1826    }
1827    TRACE_SYMTAB("rw: contains these svma regions:\n");
1828    for (i = 0; i < VG_(sizeXA)(svma_ranges); i++) {
1829       const RangeAndBias* reg = VG_(indexXA)(svma_ranges, i);
1830       if (!reg->exec)
1831          TRACE_SYMTAB("  svmas %#lx .. %#lx with bias %#lx\n",
1832                       reg->svma_base, reg->svma_limit - 1, reg->bias );
1833    }
1834 
1835    /* TOPLEVEL */
1836    /* Iterate over section headers */
1837    for (i = 0; i < shdr_mnent; i++) {
1838       ElfXX_Shdr a_shdr;
1839       ML_(img_get)(&a_shdr, mimg,
1840                    INDEX_BIS(shdr_mioff, i, shdr_ment_szB), sizeof(a_shdr));
1841       DiOffT name_mioff = shdr_strtab_mioff + a_shdr.sh_name;
1842       HChar* name = ML_(img_strdup)(mimg, "di.redi_name.1", name_mioff);
1843       Addr   svma = a_shdr.sh_addr;
1844       OffT   foff = a_shdr.sh_offset;
1845       UWord  size = a_shdr.sh_size; /* Do not change this to be signed. */
1846       UInt   alyn = a_shdr.sh_addralign;
1847       Bool   bits = !(a_shdr.sh_type == SHT_NOBITS);
1848       /* Look through our collection of info obtained from the PT_LOAD
1849          headers, and make 'inrx' and 'inrw' point to the first entry
1850          in each that intersects 'avma'.  If in each case none is found,
1851          leave the relevant pointer at NULL. */
1852       RangeAndBias* inrx = NULL;
1853       RangeAndBias* inrw = NULL;
1854       for (j = 0; j < VG_(sizeXA)(svma_ranges); j++) {
1855          RangeAndBias* rng = VG_(indexXA)(svma_ranges, j);
1856          if (svma >= rng->svma_base && svma < rng->svma_limit) {
1857             if (!inrx && rng->exec) {
1858                inrx = rng;
1859             } else if (!inrw && !rng->exec) {
1860                inrw = rng;
1861             }
1862             if (inrx && inrw)
1863                break;
1864          }
1865       }
1866 
1867       TRACE_SYMTAB(" [sec %2ld]  %s %s  al%2u  foff %6ld .. %6ld  "
1868                    "  svma %p  name \"%s\"\n",
1869                    i, inrx ? "rx" : "  ", inrw ? "rw" : "  ", alyn,
1870                    foff, foff+size-1, (void*)svma, name);
1871 
1872       /* Check for sane-sized segments.  SHT_NOBITS sections have zero
1873          size in the file. */
1874       if ((foff >= ML_(img_size)(mimg))
1875           || (foff + (bits ? size : 0) > ML_(img_size)(mimg))) {
1876          ML_(symerr)(di, True, "ELF Section extends beyond image end");
1877          goto out;
1878       }
1879 
1880       /* Check for a sane alignment value. */
1881       if (alyn > 0 && -1 == VG_(log2)(alyn)) {
1882          ML_(symerr)(di, True, "ELF Section contains invalid "
1883                                ".sh_addralign value");
1884          goto out;
1885       }
1886 
1887       /* Ignore zero sized sections. */
1888       if (size == 0) {
1889          TRACE_SYMTAB("zero sized section \"%s\", ignoring\n", name);
1890          ML_(dinfo_free)(name);
1891          continue;
1892       }
1893 
1894 #     define BAD(_secname)                                 \
1895          do { ML_(symerr)(di, True,                        \
1896                           "Can't make sense of " _secname  \
1897                           " section mapping");             \
1898               /* make sure we don't assert if we find */   \
1899               /* ourselves back in this routine later, */  \
1900               /* with the same di */                       \
1901               di->soname = NULL;                           \
1902               goto out;                                    \
1903          } while (0)
1904 
1905       /* Find avma-s for: .text .data .sdata .rodata .bss .sbss .plt .got .opd
1906          and .eh_frame */
1907 
1908       /* Accept .text where mapped as rx (code), even if zero-sized */
1909       if (0 == VG_(strcmp)(name, ".text")) {
1910          if (inrx && !di->text_present) {
1911             di->text_present = True;
1912             di->text_svma = svma;
1913             di->text_avma = svma + inrx->bias;
1914             di->text_size = size;
1915             di->text_bias = inrx->bias;
1916             di->text_debug_svma = svma;
1917             di->text_debug_bias = inrx->bias;
1918             TRACE_SYMTAB("acquiring .text svma = %#lx .. %#lx\n",
1919                          di->text_svma,
1920                          di->text_svma + di->text_size - 1);
1921             TRACE_SYMTAB("acquiring .text avma = %#lx .. %#lx\n",
1922                          di->text_avma,
1923                          di->text_avma + di->text_size - 1);
1924             TRACE_SYMTAB("acquiring .text bias = %#lx\n", di->text_bias);
1925          } else {
1926             BAD(".text");
1927          }
1928       }
1929 
1930       /* Accept .data where mapped as rw (data), even if zero-sized */
1931       if (0 == VG_(strcmp)(name, ".data")) {
1932          if (inrw && !di->data_present) {
1933             di->data_present = True;
1934             di->data_svma = svma;
1935             di->data_avma = svma + inrw->bias;
1936             di->data_size = size;
1937             di->data_bias = inrw->bias;
1938             di->data_debug_svma = svma;
1939             di->data_debug_bias = inrw->bias;
1940             TRACE_SYMTAB("acquiring .data svma = %#lx .. %#lx\n",
1941                          di->data_svma,
1942                          di->data_svma + di->data_size - 1);
1943             TRACE_SYMTAB("acquiring .data avma = %#lx .. %#lx\n",
1944                          di->data_avma,
1945                          di->data_avma + di->data_size - 1);
1946             TRACE_SYMTAB("acquiring .data bias = %#lx\n", di->data_bias);
1947          } else {
1948             BAD(".data");
1949          }
1950       }
1951 
1952       /* Accept .sdata where mapped as rw (data) */
1953       if (0 == VG_(strcmp)(name, ".sdata")) {
1954          if (inrw && !di->sdata_present) {
1955             di->sdata_present = True;
1956             di->sdata_svma = svma;
1957             di->sdata_avma = svma + inrw->bias;
1958             di->sdata_size = size;
1959             di->sdata_bias = inrw->bias;
1960             di->sdata_debug_svma = svma;
1961             di->sdata_debug_bias = inrw->bias;
1962             TRACE_SYMTAB("acquiring .sdata svma = %#lx .. %#lx\n",
1963                          di->sdata_svma,
1964                          di->sdata_svma + di->sdata_size - 1);
1965             TRACE_SYMTAB("acquiring .sdata avma = %#lx .. %#lx\n",
1966                          di->sdata_avma,
1967                          di->sdata_avma + di->sdata_size - 1);
1968             TRACE_SYMTAB("acquiring .sdata bias = %#lx\n", di->sdata_bias);
1969          } else {
1970             BAD(".sdata");
1971          }
1972       }
1973 
1974       /* Accept .rodata where mapped as rx (data), even if zero-sized */
1975       if (0 == VG_(strcmp)(name, ".rodata")) {
1976          if (inrx && !di->rodata_present) {
1977             di->rodata_present = True;
1978             di->rodata_svma = svma;
1979             di->rodata_avma = svma + inrx->bias;
1980             di->rodata_size = size;
1981             di->rodata_bias = inrx->bias;
1982             di->rodata_debug_svma = svma;
1983             di->rodata_debug_bias = inrx->bias;
1984                                     /* NB was 'inrw' prior to r11794 */
1985             TRACE_SYMTAB("acquiring .rodata svma = %#lx .. %#lx\n",
1986                          di->rodata_svma,
1987                          di->rodata_svma + di->rodata_size - 1);
1988             TRACE_SYMTAB("acquiring .rodata avma = %#lx .. %#lx\n",
1989                          di->rodata_avma,
1990                          di->rodata_avma + di->rodata_size - 1);
1991             TRACE_SYMTAB("acquiring .rodata bias = %#lx\n", di->rodata_bias);
1992          } else {
1993             BAD(".rodata");
1994          }
1995       }
1996 
1997       if (0 == VG_(strcmp)(name, ".dynbss")) {
1998          if (inrw && !di->bss_present) {
1999             dynbss_present = True;
2000             di->bss_present = True;
2001             di->bss_svma = svma;
2002             di->bss_avma = svma + inrw->bias;
2003             di->bss_size = size;
2004             di->bss_bias = inrw->bias;
2005             di->bss_debug_svma = svma;
2006             di->bss_debug_bias = inrw->bias;
2007             TRACE_SYMTAB("acquiring .dynbss svma = %#lx .. %#lx\n",
2008                          di->bss_svma,
2009                          di->bss_svma + di->bss_size - 1);
2010             TRACE_SYMTAB("acquiring .dynbss avma = %#lx .. %#lx\n",
2011                          di->bss_avma,
2012                          di->bss_avma + di->bss_size - 1);
2013             TRACE_SYMTAB("acquiring .dynbss bias = %#lx\n", di->bss_bias);
2014          }
2015       }
2016 
2017       /* Accept .bss where mapped as rw (data), even if zero-sized */
2018       if (0 == VG_(strcmp)(name, ".bss")) {
2019          if (inrw && dynbss_present) {
2020             vg_assert(di->bss_present);
2021             dynbss_present = False;
2022             vg_assert(di->bss_svma + di->bss_size == svma);
2023             di->bss_size += size;
2024             TRACE_SYMTAB("acquiring .bss svma = %#lx .. %#lx\n",
2025                          svma, svma + size - 1);
2026             TRACE_SYMTAB("acquiring .bss avma = %#lx .. %#lx\n",
2027                          svma + inrw->bias, svma + inrw->bias + size - 1);
2028             TRACE_SYMTAB("acquiring .bss bias = %#lx\n", di->bss_bias);
2029          } else
2030 
2031          if (inrw && !di->bss_present) {
2032             di->bss_present = True;
2033             di->bss_svma = svma;
2034             di->bss_avma = svma + inrw->bias;
2035             di->bss_size = size;
2036             di->bss_bias = inrw->bias;
2037             di->bss_debug_svma = svma;
2038             di->bss_debug_bias = inrw->bias;
2039             TRACE_SYMTAB("acquiring .bss svma = %#lx .. %#lx\n",
2040                          di->bss_svma,
2041                          di->bss_svma + di->bss_size - 1);
2042             TRACE_SYMTAB("acquiring .bss avma = %#lx .. %#lx\n",
2043                          di->bss_avma,
2044                          di->bss_avma + di->bss_size - 1);
2045             TRACE_SYMTAB("acquiring .bss bias = %#lx\n", di->bss_bias);
2046          } else
2047 
2048          /* Now one from the wtf?! department ... */
2049          if (inrx && (!inrw) && !di->bss_present) {
2050             /* File contains a .bss, but it got mapped as rx only.
2051                This is very strange.  For now, just pretend we didn't
2052                see it :-) */
2053             di->bss_present = False;
2054             di->bss_svma = 0;
2055             di->bss_avma = 0;
2056             di->bss_size = 0;
2057             di->bss_bias = 0;
2058             di->bss_debug_svma = 0;
2059             di->bss_debug_bias = 0;
2060             if (!VG_(clo_xml)) {
2061                VG_(message)(Vg_UserMsg,
2062                             "Warning: the following file's .bss is "
2063                             "mapped r-x only - ignoring .bss syms\n");
2064                VG_(message)(Vg_UserMsg,   " %s\n", di->fsm.filename
2065                                                       ? di->fsm.filename
2066                                                       : "(null?!)" );
2067             }
2068          } else
2069 
2070          if ((!inrw) && (!inrx) && !di->bss_present) {
2071             /* File contains a .bss, but it didn't get mapped.  Ignore. */
2072             di->bss_present = False;
2073             di->bss_svma = 0;
2074             di->bss_avma = 0;
2075             di->bss_size = 0;
2076             di->bss_bias = 0;
2077          } else {
2078             BAD(".bss");
2079          }
2080       }
2081 
2082       if (0 == VG_(strcmp)(name, ".sdynbss")) {
2083          if (inrw && !di->sbss_present) {
2084             sdynbss_present = True;
2085             di->sbss_present = True;
2086             di->sbss_svma = svma;
2087             di->sbss_avma = svma + inrw->bias;
2088             di->sbss_size = size;
2089             di->sbss_bias = inrw->bias;
2090             di->sbss_debug_svma = svma;
2091             di->sbss_debug_bias = inrw->bias;
2092             TRACE_SYMTAB("acquiring .sdynbss svma = %#lx .. %#lx\n",
2093                          di->sbss_svma,
2094                          di->sbss_svma + di->sbss_size - 1);
2095             TRACE_SYMTAB("acquiring .sdynbss avma = %#lx .. %#lx\n",
2096                          di->sbss_avma,
2097                          di->sbss_avma + di->sbss_size - 1);
2098             TRACE_SYMTAB("acquiring .sdynbss bias = %#lx\n", di->sbss_bias);
2099          }
2100       }
2101 
2102       /* Accept .sbss where mapped as rw (data) */
2103       if (0 == VG_(strcmp)(name, ".sbss")) {
2104          if (inrw && sdynbss_present) {
2105             vg_assert(di->sbss_present);
2106             sdynbss_present = False;
2107             vg_assert(di->sbss_svma + di->sbss_size == svma);
2108             di->sbss_size += size;
2109             TRACE_SYMTAB("acquiring .sbss svma = %#lx .. %#lx\n",
2110                          svma, svma + size - 1);
2111             TRACE_SYMTAB("acquiring .sbss avma = %#lx .. %#lx\n",
2112                          svma + inrw->bias, svma + inrw->bias + size - 1);
2113             TRACE_SYMTAB("acquiring .sbss bias = %#lx\n", di->sbss_bias);
2114          } else
2115 
2116          if (inrw && !di->sbss_present) {
2117             di->sbss_present = True;
2118             di->sbss_svma = svma;
2119             di->sbss_avma = svma + inrw->bias;
2120             di->sbss_size = size;
2121             di->sbss_bias = inrw->bias;
2122             di->sbss_debug_svma = svma;
2123             di->sbss_debug_bias = inrw->bias;
2124             TRACE_SYMTAB("acquiring .sbss svma = %#lx .. %#lx\n",
2125                          di->sbss_svma,
2126                          di->sbss_svma + di->sbss_size - 1);
2127             TRACE_SYMTAB("acquiring .sbss avma = %#lx .. %#lx\n",
2128                          di->sbss_avma,
2129                          di->sbss_avma + di->sbss_size - 1);
2130             TRACE_SYMTAB("acquiring .sbss bias = %#lx\n", di->sbss_bias);
2131          } else {
2132             BAD(".sbss");
2133          }
2134       }
2135 
2136       /* Accept .got where mapped as rw (data) */
2137       if (0 == VG_(strcmp)(name, ".got")) {
2138          if (inrw && !di->got_present) {
2139             di->got_present = True;
2140             di->got_avma = svma + inrw->bias;
2141             di->got_size = size;
2142             TRACE_SYMTAB("acquiring .got avma = %#lx\n", di->got_avma);
2143          } else {
2144             BAD(".got");
2145          }
2146       }
2147 
2148       /* Accept .got.plt where mapped as rw (data) */
2149       if (0 == VG_(strcmp)(name, ".got.plt")) {
2150          if (inrw && !di->gotplt_present) {
2151             di->gotplt_present = True;
2152             di->gotplt_avma = svma + inrw->bias;
2153             di->gotplt_size = size;
2154             TRACE_SYMTAB("acquiring .got.plt avma = %#lx\n", di->gotplt_avma);
2155          } else if (size != 0) {
2156             BAD(".got.plt");
2157          }
2158       }
2159 
2160       /* PLT is different on different platforms, it seems. */
2161 #     if defined(VGP_x86_linux) || defined(VGP_amd64_linux) \
2162          || defined(VGP_arm_linux) || defined (VGP_s390x_linux) \
2163          || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
2164          || defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
2165       /* Accept .plt where mapped as rx (code) */
2166       if (0 == VG_(strcmp)(name, ".plt")) {
2167          if (inrx && !di->plt_present) {
2168             di->plt_present = True;
2169             di->plt_avma = svma + inrx->bias;
2170             di->plt_size = size;
2171             TRACE_SYMTAB("acquiring .plt avma = %#lx\n", di->plt_avma);
2172          } else {
2173             BAD(".plt");
2174          }
2175       }
2176 #     elif defined(VGP_ppc32_linux)
2177       /* Accept .plt where mapped as rw (data) */
2178       if (0 == VG_(strcmp)(name, ".plt")) {
2179          if (inrw && !di->plt_present) {
2180             di->plt_present = True;
2181             di->plt_avma = svma + inrw->bias;
2182             di->plt_size = size;
2183             TRACE_SYMTAB("acquiring .plt avma = %#lx\n", di->plt_avma);
2184          } else {
2185             BAD(".plt");
2186          }
2187       }
2188 #     elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
2189       /* Accept .plt where mapped as rw (data), or unmapped */
2190       if (0 == VG_(strcmp)(name, ".plt")) {
2191          if (inrw && !di->plt_present) {
2192             di->plt_present = True;
2193             di->plt_avma = svma + inrw->bias;
2194             di->plt_size = size;
2195             TRACE_SYMTAB("acquiring .plt avma = %#lx\n", di->plt_avma);
2196          } else
2197          if ((!inrw) && (!inrx) && size > 0 && !di->plt_present) {
2198             /* File contains a .plt, but it didn't get mapped.
2199                Presumably it is not required on this platform.  At
2200                least don't reject the situation as invalid. */
2201             di->plt_present = True;
2202             di->plt_avma = 0;
2203             di->plt_size = 0;
2204          } else {
2205             BAD(".plt");
2206          }
2207       }
2208 #     else
2209 #       error "Unsupported platform"
2210 #     endif
2211 
2212       /* Accept .opd where mapped as rw (data) */
2213       if (0 == VG_(strcmp)(name, ".opd")) {
2214          if (inrw && !di->opd_present) {
2215             di->opd_present = True;
2216             di->opd_avma = svma + inrw->bias;
2217             di->opd_size = size;
2218             TRACE_SYMTAB("acquiring .opd avma = %#lx\n", di->opd_avma);
2219          } else {
2220             BAD(".opd");
2221          }
2222       }
2223 
2224       /* Accept .eh_frame where mapped as rx (code).  This seems to be
2225          the common case.  However, if that doesn't pan out, try for
2226          rw (data) instead.  We can handle up to N_EHFRAME_SECTS per
2227          ELF object. */
2228       if (0 == VG_(strcmp)(name, ".eh_frame")) {
2229          if (inrx && di->n_ehframe < N_EHFRAME_SECTS) {
2230             di->ehframe_avma[di->n_ehframe] = svma + inrx->bias;
2231             di->ehframe_size[di->n_ehframe] = size;
2232             TRACE_SYMTAB("acquiring .eh_frame avma = %#lx\n",
2233                          di->ehframe_avma[di->n_ehframe]);
2234             di->n_ehframe++;
2235          } else
2236          if (inrw && di->n_ehframe < N_EHFRAME_SECTS) {
2237             di->ehframe_avma[di->n_ehframe] = svma + inrw->bias;
2238             di->ehframe_size[di->n_ehframe] = size;
2239             TRACE_SYMTAB("acquiring .eh_frame avma = %#lx\n",
2240                          di->ehframe_avma[di->n_ehframe]);
2241             di->n_ehframe++;
2242          } else {
2243             BAD(".eh_frame");
2244          }
2245       }
2246 
2247       /* Accept .ARM.exidx where mapped as rx (code). */
2248       /* FIXME: make sure the entire section is mapped in, not just
2249          the first address. */
2250       if (0 == VG_(strcmp)(name, ".ARM.exidx")) {
2251          if (inrx && !di->exidx_present) {
2252             di->exidx_present = True;
2253             di->exidx_svma = svma;
2254             di->exidx_avma = svma + inrx->bias;
2255             di->exidx_size = size;
2256             di->exidx_bias = inrx->bias;
2257             TRACE_SYMTAB("acquiring .exidx svma = %#lx .. %#lx\n",
2258                          di->exidx_svma,
2259                          di->exidx_svma + di->exidx_size - 1);
2260             TRACE_SYMTAB("acquiring .exidx avma = %#lx .. %#lx\n",
2261                          di->exidx_avma,
2262                          di->exidx_avma + di->exidx_size - 1);
2263             TRACE_SYMTAB("acquiring .exidx bias = %#lx\n", di->exidx_bias);
2264          } else {
2265             BAD(".ARM.exidx");
2266          }
2267       }
2268 
2269       /* Accept .ARM.extab where mapped as rx (code). */
2270       /* FIXME: make sure the entire section is mapped in, not just
2271          the first address. */
2272       if (0 == VG_(strcmp)(name, ".ARM.extab")) {
2273          if (inrx && !di->extab_present) {
2274             di->extab_present = True;
2275             di->extab_svma = svma;
2276             di->extab_avma = svma + inrx->bias;
2277             di->extab_size = size;
2278             di->extab_bias = inrx->bias;
2279             TRACE_SYMTAB("acquiring .extab svma = %#lx .. %#lx\n",
2280                          di->extab_svma,
2281                          di->extab_svma + di->extab_size - 1);
2282             TRACE_SYMTAB("acquiring .extab avma = %#lx .. %#lx\n",
2283                          di->extab_avma,
2284                          di->extab_avma + di->extab_size - 1);
2285             TRACE_SYMTAB("acquiring .extab bias = %#lx\n", di->extab_bias);
2286          } else {
2287             BAD(".ARM.extab");
2288          }
2289       }
2290 
2291       ML_(dinfo_free)(name);
2292 
2293 #     undef BAD
2294 
2295    } /* iterate over the section headers */
2296 
2297    /* TOPLEVEL */
2298    if (0) VG_(printf)("YYYY text_: avma %#lx  size %ld  bias %#lx\n",
2299                       di->text_avma, di->text_size, di->text_bias);
2300 
2301    if (VG_(clo_verbosity) > 2 || VG_(clo_trace_redir))
2302       VG_(message)(Vg_DebugMsg, "   svma %#010lx, avma %#010lx\n",
2303                                 di->text_avma - di->text_bias,
2304                                 di->text_avma );
2305 
2306    TRACE_SYMTAB("\n");
2307    TRACE_SYMTAB("------ Finding image addresses "
2308                 "for debug-info sections ------\n");
2309 
2310    /* TOPLEVEL */
2311    /* Find interesting sections, read the symbol table(s), read any
2312       debug information.  Each section is located either in the main,
2313       debug or alt-debug files, but only in one.  For each section,
2314       |section_escn| records which of |mimg|, |dimg| or |aimg| we
2315       found it in, along with the section's image offset and its size.
2316       The triples (section_img, section_ioff, section_szB) are
2317       consistent, in that they are always either (NULL,
2318       DiOffT_INVALID, 0), or refer to the same image, and are all
2319       assigned together. */
2320    {
2321       /* TOPLEVEL */
2322       DiSlice strtab_escn         = DiSlice_INVALID; // .strtab
2323       DiSlice symtab_escn         = DiSlice_INVALID; // .symtab
2324       DiSlice dynstr_escn         = DiSlice_INVALID; // .dynstr
2325       DiSlice dynsym_escn         = DiSlice_INVALID; // .dynsym
2326       DiSlice debuglink_escn      = DiSlice_INVALID; // .gnu_debuglink
2327       DiSlice debugaltlink_escn   = DiSlice_INVALID; // .gnu_debugaltlink
2328       DiSlice debug_line_escn     = DiSlice_INVALID; // .debug_line   (dwarf2)
2329       DiSlice debug_info_escn     = DiSlice_INVALID; // .debug_info   (dwarf2)
2330       DiSlice debug_types_escn    = DiSlice_INVALID; // .debug_types  (dwarf4)
2331       DiSlice debug_abbv_escn     = DiSlice_INVALID; // .debug_abbrev (dwarf2)
2332       DiSlice debug_str_escn      = DiSlice_INVALID; // .debug_str    (dwarf2)
2333       DiSlice debug_ranges_escn   = DiSlice_INVALID; // .debug_ranges (dwarf2)
2334       DiSlice debug_loc_escn      = DiSlice_INVALID; // .debug_loc    (dwarf2)
2335       DiSlice debug_frame_escn    = DiSlice_INVALID; // .debug_frame  (dwarf2)
2336       DiSlice debug_line_alt_escn = DiSlice_INVALID; // .debug_line   (alt)
2337       DiSlice debug_info_alt_escn = DiSlice_INVALID; // .debug_info   (alt)
2338       DiSlice debug_abbv_alt_escn = DiSlice_INVALID; // .debug_abbrev (alt)
2339       DiSlice debug_str_alt_escn  = DiSlice_INVALID; // .debug_str    (alt)
2340       DiSlice dwarf1d_escn        = DiSlice_INVALID; // .debug        (dwarf1)
2341       DiSlice dwarf1l_escn        = DiSlice_INVALID; // .line         (dwarf1)
2342       DiSlice opd_escn            = DiSlice_INVALID; // .opd (dwarf2,
2343                                                      //       ppc64be-linux)
2344       DiSlice ehframe_escn[N_EHFRAME_SECTS];         // .eh_frame (dwarf2)
2345 
2346       for (i = 0; i < N_EHFRAME_SECTS; i++)
2347          ehframe_escn[i] = DiSlice_INVALID;
2348 
2349       /* Find all interesting sections */
2350 
2351       UInt ehframe_mix = 0;
2352 
2353       /* What FIND does: it finds the section called _SEC_NAME.  The
2354          size of it is assigned to _SEC_SIZE.  The address of the
2355          section in the transiently loaded oimage is assigned to
2356          _SEC_IMG.  If the section is found, _POST_FX is executed
2357          after _SEC_NAME and _SEC_SIZE have been assigned to.
2358 
2359          Even for sections which are marked loadable, the client's
2360          ld.so may not have loaded them yet, so there is no guarantee
2361          that we can safely prod around in any such area).  Because
2362          the entire object file is transiently mapped aboard for
2363          inspection, it's always safe to inspect that area. */
2364 
2365       /* TOPLEVEL */
2366       /* Iterate over section headers (again) */
2367       for (i = 0; i < ehdr_m.e_shnum; i++) {
2368 
2369 #        define FINDX(_sec_name, _sec_escn, _post_fx) \
2370          do { \
2371             ElfXX_Shdr a_shdr; \
2372             ML_(img_get)(&a_shdr, mimg, \
2373                          INDEX_BIS(shdr_mioff, i, shdr_ment_szB), \
2374                          sizeof(a_shdr)); \
2375             if (0 == ML_(img_strcmp_c)(mimg, shdr_strtab_mioff \
2376                                               + a_shdr.sh_name, _sec_name)) { \
2377                Bool nobits; \
2378                _sec_escn.img  = mimg; \
2379                _sec_escn.ioff = (DiOffT)a_shdr.sh_offset; \
2380                _sec_escn.szB  = a_shdr.sh_size; \
2381                nobits         = a_shdr.sh_type == SHT_NOBITS; \
2382                vg_assert(_sec_escn.img  != NULL); \
2383                vg_assert(_sec_escn.ioff != DiOffT_INVALID); \
2384                TRACE_SYMTAB( "%-18s:  ioff %llu .. %llu\n", \
2385                              _sec_name, (ULong)_sec_escn.ioff, \
2386                              ((ULong)_sec_escn.ioff) + _sec_escn.szB - 1); \
2387                /* SHT_NOBITS sections have zero size in the file. */ \
2388                if ( a_shdr.sh_offset \
2389                     + (nobits ? 0 : _sec_escn.szB) > ML_(img_size)(mimg) ) { \
2390                   ML_(symerr)(di, True, \
2391                               "   section beyond image end?!"); \
2392                   goto out; \
2393                } \
2394                _post_fx; \
2395             } \
2396          } while (0);
2397 
2398          /* Version with no post-effects */
2399 #        define FIND(_sec_name, _sec_escn) \
2400             FINDX(_sec_name, _sec_escn, /**/)
2401 
2402          /*   NAME                  ElfSec */
2403          FIND(".dynsym",            dynsym_escn)
2404          FIND(".dynstr",            dynstr_escn)
2405          FIND(".symtab",            symtab_escn)
2406          FIND(".strtab",            strtab_escn)
2407 
2408          FIND(".gnu_debuglink",     debuglink_escn)
2409          FIND(".gnu_debugaltlink",  debugaltlink_escn)
2410 
2411          FIND(".debug_line",        debug_line_escn)
2412          FIND(".debug_info",        debug_info_escn)
2413          FIND(".debug_types",       debug_types_escn)
2414          FIND(".debug_abbrev",      debug_abbv_escn)
2415          FIND(".debug_str",         debug_str_escn)
2416          FIND(".debug_ranges",      debug_ranges_escn)
2417          FIND(".debug_loc",         debug_loc_escn)
2418          FIND(".debug_frame",       debug_frame_escn)
2419 
2420          FIND(".debug",             dwarf1d_escn)
2421          FIND(".line",              dwarf1l_escn)
2422 
2423          FIND(".opd",               opd_escn)
2424 
2425          FINDX(".eh_frame",         ehframe_escn[ehframe_mix],
2426                do { ehframe_mix++; vg_assert(ehframe_mix <= N_EHFRAME_SECTS);
2427                } while (0)
2428          )
2429          /* Comment_on_EH_FRAME_MULTIPLE_INSTANCES: w.r.t. .eh_frame
2430             multi-instance kludgery, how are we assured that the order
2431             in which we fill in ehframe_escn[] is consistent with the
2432             order in which we previously filled in di->ehframe_avma[]
2433             and di->ehframe_size[] ?  By the fact that in both cases,
2434             these arrays were filled in by iterating over the section
2435             headers top-to-bottom.  So both loops (this one and the
2436             previous one) encounter the .eh_frame entries in the same
2437             order and so fill in these arrays in a consistent order.
2438          */
2439 
2440 #        undef FINDX
2441 #        undef FIND
2442       } /* Iterate over section headers (again) */
2443 
2444       /* TOPLEVEL */
2445       /* Now, see if we can find a debuginfo object, and if so connect
2446          |dimg| to it. */
2447       vg_assert(dimg == NULL && aimg == NULL);
2448 
2449       /* Look for a build-id */
2450       HChar* buildid = find_buildid(mimg, False, False);
2451 
2452       /* Look for a debug image that matches either the build-id or
2453          the debuglink-CRC32 in the main image.  If the main image
2454          doesn't contain either of those then this won't even bother
2455          to try looking.  This looks in all known places, including
2456          the --extra-debuginfo-path if specified and on the
2457          --debuginfo-server if specified. */
2458       if (buildid != NULL || debuglink_escn.img != NULL) {
2459          /* Do have a debuglink section? */
2460          if (debuglink_escn.img != NULL) {
2461             UInt crc_offset
2462                = VG_ROUNDUP(ML_(img_strlen)(debuglink_escn.img,
2463                                             debuglink_escn.ioff)+1, 4);
2464             vg_assert(crc_offset + sizeof(UInt) <= debuglink_escn.szB);
2465 
2466             /* Extract the CRC from the debuglink section */
2467             UInt crc = ML_(img_get_UInt)(debuglink_escn.img,
2468                                          debuglink_escn.ioff + crc_offset);
2469 
2470             /* See if we can find a matching debug file */
2471             HChar* debuglink_str_m
2472                = ML_(img_strdup)(debuglink_escn.img,
2473                                  "di.redi_dlk.1", debuglink_escn.ioff);
2474             dimg = find_debug_file( di, di->fsm.filename, buildid,
2475                                     debuglink_str_m, crc, False );
2476             if (debuglink_str_m)
2477                ML_(dinfo_free)(debuglink_str_m);
2478          } else {
2479             /* See if we can find a matching debug file */
2480             dimg = find_debug_file( di, di->fsm.filename, buildid,
2481                                     NULL, 0, False );
2482          }
2483       }
2484 
2485       if (buildid) {
2486          ML_(dinfo_free)(buildid);
2487          buildid = NULL; /* paranoia */
2488       }
2489 
2490       /* As a last-ditch measure, try looking for in the
2491          --extra-debuginfo-path and/or on the --debuginfo-server, but
2492          only in the case where --allow-mismatched-debuginfo=yes.
2493          This is dangerous in that (1) it gives no assurance that the
2494          debuginfo object matches the main one, and hence (2) we will
2495          very likely get an assertion in the code below, if indeed
2496          there is a mismatch.  Hence it is disabled by default
2497          (--allow-mismatched-debuginfo=no).  Nevertheless it's
2498          sometimes a useful way of getting out of a tight spot.
2499 
2500          Note that we're ignoring the name in the .gnu_debuglink
2501          section here, and just looking for a file of the same name
2502          either the extra-path or on the server. */
2503       if (dimg == NULL && VG_(clo_allow_mismatched_debuginfo)) {
2504          dimg = find_debug_file_ad_hoc( di, di->fsm.filename );
2505       }
2506 
2507       /* TOPLEVEL */
2508       /* If we were successful in finding a debug image, pull various
2509          SVMA/bias/size and image addresses out of it. */
2510       if (dimg != NULL && is_elf_object_file_by_DiImage(dimg, False)) {
2511 
2512          /* Pull out and validate program header and section header info */
2513          DiOffT      ehdr_dioff = 0;
2514          ElfXX_Ehdr  ehdr_dimg;
2515          ML_(img_get)(&ehdr_dimg, dimg, ehdr_dioff, sizeof(ehdr_dimg));
2516 
2517          DiOffT   phdr_dioff        = ehdr_dimg.e_phoff;
2518          UWord    phdr_dnent        = ehdr_dimg.e_phnum;
2519          UWord    phdr_dent_szB     = ehdr_dimg.e_phentsize;
2520 
2521          DiOffT   shdr_dioff        = ehdr_dimg.e_shoff;
2522          UWord    shdr_dnent        = ehdr_dimg.e_shnum;
2523          UWord    shdr_dent_szB     = ehdr_dimg.e_shentsize;
2524 
2525          DiOffT   shdr_strtab_dioff = DiOffT_INVALID;
2526 
2527          /* SVMAs covered by rx and rw segments and corresponding bias. */
2528          Addr     rx_dsvma_limit = 0;
2529          PtrdiffT rx_dbias = 0;
2530          Addr     rw_dsvma_limit = 0;
2531          PtrdiffT rw_dbias = 0;
2532 
2533          Bool need_symtab, need_dwarf2, need_dwarf1;
2534 
2535          if (phdr_dnent == 0
2536              || !ML_(img_valid)(dimg, phdr_dioff,
2537                                 phdr_dnent * phdr_dent_szB)) {
2538             ML_(symerr)(di, True,
2539                         "Missing or invalid ELF Program Header Table"
2540                         " (debuginfo file)");
2541             goto out;
2542          }
2543 
2544          if (shdr_dnent == 0
2545              || !ML_(img_valid)(dimg, shdr_dioff,
2546                                 shdr_dnent * shdr_dent_szB)) {
2547             ML_(symerr)(di, True,
2548                         "Missing or invalid ELF Section Header Table"
2549                         " (debuginfo file)");
2550             goto out;
2551          }
2552 
2553          /* Also find the section header's string table, and validate. */
2554          /* checked previously by is_elf_object_file: */
2555          vg_assert(ehdr_dimg.e_shstrndx != SHN_UNDEF);
2556 
2557          // shdr_dioff is the offset of the section header table
2558          // and we need the ehdr_dimg.e_shstrndx'th entry
2559          { ElfXX_Shdr a_shdr;
2560            ML_(img_get)(&a_shdr, dimg,
2561                         INDEX_BIS(shdr_dioff, ehdr_dimg.e_shstrndx,
2562                                               shdr_dent_szB),
2563                         sizeof(a_shdr));
2564            shdr_strtab_dioff = a_shdr.sh_offset;
2565            if (!ML_(img_valid)(dimg, shdr_strtab_dioff,
2566                                1/*bogus, but we don't know the real size*/)) {
2567               ML_(symerr)(di, True,
2568                           "Invalid ELF Section Header String Table"
2569                           " (debuginfo file)");
2570               goto out;
2571            }
2572          }
2573 
2574          for (i = 0; i < ehdr_dimg.e_phnum; i++) {
2575             ElfXX_Phdr a_phdr;
2576             ML_(img_get)(&a_phdr, dimg, INDEX_BIS(ehdr_dimg.e_phoff,
2577                                                   i, phdr_dent_szB),
2578                            sizeof(a_phdr));
2579             if (a_phdr.p_type == PT_LOAD) {
2580                for (j = 0; j < VG_(sizeXA)(di->fsm.maps); j++) {
2581                   const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, j);
2582                   if (   a_phdr.p_offset >= map->foff
2583                       && a_phdr.p_offset <  map->foff + map->size
2584                       && a_phdr.p_offset + a_phdr.p_filesz
2585                          < map->foff + map->size) {
2586                      if (map->rx && rx_dsvma_limit == 0) {
2587                         rx_dsvma_limit = a_phdr.p_vaddr + a_phdr.p_memsz;
2588                         rx_dbias = map->avma - map->foff + a_phdr.p_offset
2589                                    - a_phdr.p_vaddr;
2590                      }
2591                      if (map->rw && rw_dsvma_limit == 0) {
2592                         rw_dsvma_limit = a_phdr.p_vaddr + a_phdr.p_memsz;
2593                         rw_dbias = map->avma - map->foff + a_phdr.p_offset
2594                                    - a_phdr.p_vaddr;
2595                      }
2596                      break;
2597                   }
2598                }
2599             }
2600          }
2601 
2602          need_symtab = (symtab_escn.img == NULL);
2603          need_dwarf2 = (debug_info_escn.img == NULL);
2604          need_dwarf1 = (dwarf1d_escn.img == NULL);
2605 
2606          /* Find all interesting sections in the debug image */
2607          for (i = 0; i < ehdr_dimg.e_shnum; i++) {
2608 
2609             /* Find debug svma and bias information for sections
2610                we found in the main file. */
2611 
2612 #           define FIND(_sec, _seg) \
2613             do { \
2614                ElfXX_Shdr a_shdr; \
2615                ML_(img_get)(&a_shdr, dimg, \
2616                             INDEX_BIS(shdr_dioff, i, shdr_dent_szB), \
2617                             sizeof(a_shdr)); \
2618                if (di->_sec##_present \
2619                    && 0 == ML_(img_strcmp_c)(dimg, shdr_strtab_dioff \
2620                                              + a_shdr.sh_name, "." #_sec)) { \
2621                   vg_assert(di->_sec##_size == a_shdr.sh_size); \
2622                   /* JRS 2013-Jun-01: the following assert doesn't contain */ \
2623                   /* any ==s, which seems to me to be suspicious. */ \
2624                   vg_assert(di->_sec##_avma +  a_shdr.sh_addr + _seg##_dbias); \
2625                   /* Assume we have a correct value for the main */ \
2626                   /* object's bias.  Use that to derive the debuginfo */ \
2627                   /* object's bias, by adding the difference in SVMAs */ \
2628                   /* for the corresponding sections in the two files. */ \
2629                   /* That should take care of all prelinking effects. */ \
2630                   di->_sec##_debug_svma = a_shdr.sh_addr; \
2631                   di->_sec##_debug_bias \
2632                      = di->_sec##_bias + \
2633                        di->_sec##_svma - di->_sec##_debug_svma; \
2634                   TRACE_SYMTAB("acquiring ." #_sec \
2635                                " debug svma = %#lx .. %#lx\n",       \
2636                                di->_sec##_debug_svma, \
2637                                di->_sec##_debug_svma + di->_sec##_size - 1); \
2638                   TRACE_SYMTAB("acquiring ." #_sec " debug bias = %#lx\n", \
2639                                di->_sec##_debug_bias); \
2640                } \
2641             } while (0);
2642 
2643             /* SECTION   SEGMENT */
2644             FIND(text,   rx)
2645             FIND(data,   rw)
2646             FIND(sdata,  rw)
2647             FIND(rodata, rw)
2648             FIND(bss,    rw)
2649             FIND(sbss,   rw)
2650 
2651 #           undef FIND
2652 
2653             /* Same deal as previous FIND, except only do it for those
2654                sections which we didn't find in the main file. */
2655 
2656 #           define FIND(_condition, _sec_name, _sec_escn) \
2657             do { \
2658                ElfXX_Shdr a_shdr; \
2659                ML_(img_get)(&a_shdr, dimg, \
2660                             INDEX_BIS(shdr_dioff, i, shdr_dent_szB), \
2661                             sizeof(a_shdr)); \
2662                if (_condition \
2663                    && 0 == ML_(img_strcmp_c)(dimg, shdr_strtab_dioff \
2664                                              + a_shdr.sh_name, _sec_name)) { \
2665                   Bool nobits; \
2666                   if (_sec_escn.img != NULL) { \
2667                      ML_(symerr)(di, True, \
2668                                  "   debuginfo section duplicates a" \
2669                                  " section in the main ELF file"); \
2670                      goto out; \
2671                   } \
2672                   _sec_escn.img  = dimg; \
2673                   _sec_escn.ioff = (DiOffT)a_shdr.sh_offset;  \
2674                   _sec_escn.szB  = a_shdr.sh_size; \
2675                   nobits         = a_shdr.sh_type == SHT_NOBITS; \
2676                   vg_assert(_sec_escn.img  != NULL); \
2677                   vg_assert(_sec_escn.ioff != DiOffT_INVALID); \
2678                   TRACE_SYMTAB( "%-18s: dioff %llu .. %llu\n", \
2679                                 _sec_name, \
2680                                 (ULong)_sec_escn.ioff, \
2681                                 ((ULong)_sec_escn.ioff) + _sec_escn.szB - 1); \
2682                   /* SHT_NOBITS sections have zero size in the file. */ \
2683                   if (a_shdr.sh_offset \
2684                       + (nobits ? 0 : _sec_escn.szB) > ML_(img_size)(dimg)) { \
2685                      ML_(symerr)(di, True, \
2686                                  "   section beyond image end?!"); \
2687                      goto out; \
2688                   } \
2689                } \
2690             } while (0);
2691 
2692             /* NEEDED?        NAME             ElfSec */
2693             FIND(need_symtab, ".symtab",       symtab_escn)
2694             FIND(need_symtab, ".strtab",       strtab_escn)
2695             FIND(need_dwarf2, ".debug_line",   debug_line_escn)
2696             FIND(need_dwarf2, ".debug_info",   debug_info_escn)
2697             FIND(need_dwarf2, ".debug_types",  debug_types_escn)
2698 
2699             FIND(need_dwarf2, ".debug_abbrev", debug_abbv_escn)
2700             FIND(need_dwarf2, ".debug_str",    debug_str_escn)
2701             FIND(need_dwarf2, ".debug_ranges", debug_ranges_escn)
2702 
2703             FIND(need_dwarf2, ".debug_loc",    debug_loc_escn)
2704             FIND(need_dwarf2, ".debug_frame",  debug_frame_escn)
2705 
2706             FIND(need_dwarf2, ".gnu_debugaltlink", debugaltlink_escn)
2707 
2708             FIND(need_dwarf1, ".debug",        dwarf1d_escn)
2709             FIND(need_dwarf1, ".line",         dwarf1l_escn)
2710 
2711 #           undef FIND
2712          } /* Find all interesting sections */
2713       } /* do we have a debug image? */
2714 
2715       /* TOPLEVEL */
2716       /* Look for alternate debug image, and if found, connect |aimg|
2717          to it. */
2718       vg_assert(aimg == NULL);
2719 
2720       if (debugaltlink_escn.img != NULL) {
2721          HChar* altfile_str_m
2722              = ML_(img_strdup)(debugaltlink_escn.img,
2723                                "di.fbi.3", debugaltlink_escn.ioff);
2724          UInt buildid_offset = ML_(img_strlen)(debugaltlink_escn.img,
2725                                                debugaltlink_escn.ioff)+1;
2726 
2727          vg_assert(buildid_offset < debugaltlink_escn.szB);
2728 
2729          HChar *altbuildid
2730             = ML_(dinfo_zalloc)("di.fbi.4",
2731                                 (debugaltlink_escn.szB - buildid_offset)
2732                                 * 2 + 1);
2733 
2734          /* The altfile might be relative to the debug file or main file. */
2735          HChar *dbgname = di->fsm.dbgname ? di->fsm.dbgname : di->fsm.filename;
2736 
2737          for (j = 0; j < debugaltlink_escn.szB - buildid_offset; j++)
2738             VG_(sprintf)(
2739                altbuildid + 2 * j, "%02x",
2740                (UInt)ML_(img_get_UChar)(debugaltlink_escn.img,
2741                                         debugaltlink_escn.ioff
2742                                         + buildid_offset + j));
2743 
2744          /* See if we can find a matching debug file */
2745          aimg = find_debug_file( di, dbgname, altbuildid,
2746                                  altfile_str_m, 0, True );
2747 
2748          if (altfile_str_m)
2749             ML_(dinfo_free)(altfile_str_m);
2750          ML_(dinfo_free)(altbuildid);
2751       }
2752 
2753       /* TOPLEVEL */
2754       /* If we were successful in finding alternate debug image, pull various
2755          size and image addresses out of it. */
2756       if (aimg != NULL && is_elf_object_file_by_DiImage(aimg, True)) {
2757 
2758          /* Pull out and validate program header and section header info */
2759          DiOffT      ehdr_aioff = 0;
2760          ElfXX_Ehdr  ehdr_aimg;
2761          ML_(img_get)(&ehdr_aimg, aimg, ehdr_aioff, sizeof(ehdr_aimg));
2762 
2763          DiOffT   shdr_aioff        = ehdr_aimg.e_shoff;
2764          UWord    shdr_anent        = ehdr_aimg.e_shnum;
2765          UWord    shdr_aent_szB     = ehdr_aimg.e_shentsize;
2766 
2767          DiOffT   shdr_strtab_aioff = DiOffT_INVALID;
2768 
2769          if (shdr_anent == 0
2770              || !ML_(img_valid)(aimg, shdr_aioff,
2771                                 shdr_anent * shdr_aent_szB)) {
2772             ML_(symerr)(di, True,
2773                         "Missing or invalid ELF Section Header Table"
2774                         " (alternate debuginfo file)");
2775             goto out;
2776          }
2777 
2778          /* Also find the section header's string table, and validate. */
2779          /* checked previously by is_elf_object_file: */
2780          vg_assert(ehdr_aimg.e_shstrndx != SHN_UNDEF);
2781 
2782          // shdr_aioff is the offset of the section header table
2783          // and we need the ehdr_aimg.e_shstrndx'th entry
2784          { ElfXX_Shdr a_shdr;
2785            ML_(img_get)(&a_shdr, aimg,
2786                         INDEX_BIS(shdr_aioff, ehdr_aimg.e_shstrndx,
2787                                               shdr_aent_szB),
2788                         sizeof(a_shdr));
2789            shdr_strtab_aioff = a_shdr.sh_offset;
2790            if (!ML_(img_valid)(aimg, shdr_strtab_aioff,
2791                                1/*bogus, but we don't know the real size*/)) {
2792               ML_(symerr)(di, True,
2793                           "Invalid ELF Section Header String Table"
2794                           " (alternate debuginfo file)");
2795               goto out;
2796            }
2797          }
2798 
2799          /* Find all interesting sections */
2800          for (i = 0; i < ehdr_aimg.e_shnum; i++) {
2801 
2802 #           define FIND(_sec_name, _sec_escn) \
2803             do { \
2804                ElfXX_Shdr a_shdr; \
2805                ML_(img_get)(&a_shdr, aimg, \
2806                             INDEX_BIS(shdr_aioff, i, shdr_aent_szB), \
2807                             sizeof(a_shdr)); \
2808                if (0 == ML_(img_strcmp_c)(aimg, shdr_strtab_aioff \
2809                                           + a_shdr.sh_name, _sec_name)) { \
2810                   if (_sec_escn.img != NULL) { \
2811                      ML_(symerr)(di, True, \
2812                                  "   alternate debuginfo section duplicates a" \
2813                                  " section in the main ELF file"); \
2814                      goto out; \
2815                   } \
2816                   _sec_escn.img  = aimg; \
2817                   _sec_escn.ioff = (DiOffT)a_shdr.sh_offset; \
2818                   _sec_escn.szB  = a_shdr.sh_size; \
2819                   vg_assert(_sec_escn.img  != NULL); \
2820                   vg_assert(_sec_escn.ioff != DiOffT_INVALID); \
2821                   TRACE_SYMTAB( "%-18s: aioff %llu .. %llu\n", \
2822                                 _sec_name, \
2823                                 (ULong)_sec_escn.ioff, \
2824                                 ((ULong)_sec_escn.ioff) + _sec_escn.szB - 1); \
2825                } \
2826             } while (0);
2827 
2828             /*   NAME             ElfSec */
2829             FIND(".debug_line",   debug_line_alt_escn)
2830             FIND(".debug_info",   debug_info_alt_escn)
2831             FIND(".debug_abbrev", debug_abbv_alt_escn)
2832             FIND(".debug_str",    debug_str_alt_escn)
2833 
2834 #           undef FIND
2835          } /* Find all interesting sections */
2836       } /* do we have a debug image? */
2837 
2838 
2839       /* TOPLEVEL */
2840       /* Check some sizes */
2841       vg_assert((dynsym_escn.szB % sizeof(ElfXX_Sym)) == 0);
2842       vg_assert((symtab_escn.szB % sizeof(ElfXX_Sym)) == 0);
2843 
2844       /* TOPLEVEL */
2845       /* Read symbols */
2846       {
2847          void (*read_elf_symtab)(struct _DebugInfo*, const HChar*,
2848                                  DiSlice*, DiSlice*, DiSlice*, Bool);
2849          Bool symtab_in_debug;
2850 #        if defined(VGP_ppc64be_linux)
2851          read_elf_symtab = read_elf_symtab__ppc64be_linux;
2852 #        else
2853          read_elf_symtab = read_elf_symtab__normal;
2854 #        endif
2855          symtab_in_debug = symtab_escn.img == dimg;
2856          read_elf_symtab(di, "symbol table",
2857                          &symtab_escn, &strtab_escn, &opd_escn,
2858                          symtab_in_debug);
2859          read_elf_symtab(di, "dynamic symbol table",
2860                          &dynsym_escn, &dynstr_escn, &opd_escn,
2861                          False);
2862       }
2863 
2864       /* TOPLEVEL */
2865       /* Read .eh_frame and .debug_frame (call-frame-info) if any.  Do
2866          the .eh_frame section(s) first. */
2867       vg_assert(di->n_ehframe >= 0 && di->n_ehframe <= N_EHFRAME_SECTS);
2868       for (i = 0; i < di->n_ehframe; i++) {
2869          /* see Comment_on_EH_FRAME_MULTIPLE_INSTANCES above for why
2870             this next assertion should hold. */
2871          vg_assert(ML_(sli_is_valid)(ehframe_escn[i]));
2872          vg_assert(ehframe_escn[i].szB == di->ehframe_size[i]);
2873          ML_(read_callframe_info_dwarf3)( di,
2874                                           ehframe_escn[i],
2875                                           di->ehframe_avma[i],
2876                                           True/*is_ehframe*/ );
2877       }
2878       if (ML_(sli_is_valid)(debug_frame_escn)) {
2879          ML_(read_callframe_info_dwarf3)( di,
2880                                           debug_frame_escn,
2881                                           0/*assume zero avma*/,
2882                                           False/*!is_ehframe*/ );
2883       }
2884 
2885       /* TOPLEVEL */
2886       /* jrs 2006-01-01: icc-8.1 has been observed to generate
2887          binaries without debug_str sections.  Don't preclude
2888          debuginfo reading for that reason, but, in
2889          read_unitinfo_dwarf2, do check that debugstr is non-NULL
2890          before using it. */
2891       if (ML_(sli_is_valid)(debug_info_escn)
2892           && ML_(sli_is_valid)(debug_abbv_escn)
2893           && ML_(sli_is_valid)(debug_line_escn)) {
2894          /* The old reader: line numbers and unwind info only */
2895          ML_(read_debuginfo_dwarf3) ( di,
2896                                       debug_info_escn,
2897                                       debug_types_escn,
2898                                       debug_abbv_escn,
2899                                       debug_line_escn,
2900                                       debug_str_escn,
2901                                       debug_str_alt_escn );
2902          /* The new reader: read the DIEs in .debug_info to acquire
2903             information on variable types and locations or inline info.
2904             But only if the tool asks for it, or the user requests it on
2905             the command line. */
2906          if (VG_(clo_read_var_info) /* the user or tool asked for it */
2907              || VG_(clo_read_inline_info)) {
2908             ML_(new_dwarf3_reader)(
2909                di, debug_info_escn,     debug_types_escn,
2910                    debug_abbv_escn,     debug_line_escn,
2911                    debug_str_escn,      debug_ranges_escn,
2912                    debug_loc_escn,      debug_info_alt_escn,
2913                    debug_abbv_alt_escn, debug_line_alt_escn,
2914                    debug_str_alt_escn
2915             );
2916          }
2917       }
2918 
2919       /* TOPLEVEL */
2920       // JRS 31 July 2014: dwarf-1 reading is currently broken and
2921       // therefore deactivated.
2922       //if (dwarf1d_img && dwarf1l_img) {
2923       //   ML_(read_debuginfo_dwarf1) ( di, dwarf1d_img, dwarf1d_sz,
2924       //                                    dwarf1l_img, dwarf1l_sz );
2925       //}
2926 
2927 #     if defined(VGA_arm)
2928       /* TOPLEVEL */
2929       /* ARM32 only: read .exidx/.extab if present.  Note we are
2930          reading these directly out of the mapped in (running) image.
2931          Also, read these only if no CFI based unwind info was
2932          acquired for this file.
2933 
2934          An .exidx section is always required, but the .extab section
2935          can be optionally omitted, provided that .exidx does not
2936          refer to it.  If the .exidx is erroneous and does refer to
2937          .extab even though .extab is missing, the range checks done
2938          by GET_EX_U32 in ExtabEntryExtract in readexidx.c should
2939          prevent any invalid memory accesses, and cause the .extab to
2940          be rejected as invalid.
2941 
2942          FIXME:
2943          * check with m_aspacemgr that the entire [exidx_avma, +exidx_size)
2944            and [extab_avma, +extab_size) areas are readable, since we're
2945            reading this stuff out of the running image (not from a file/socket)
2946            and we don't want to segfault.
2947          * DebugInfo::exidx_bias and use text_bias instead.
2948            I think it's always the same.
2949          * remove DebugInfo::{extab_bias, exidx_svma, extab_svma} since
2950            they are never used.
2951       */
2952       if (di->exidx_present
2953           && di->cfsi_used == 0
2954           && di->text_present && di->text_size > 0) {
2955          Addr text_last_svma = di->text_svma + di->text_size - 1;
2956          ML_(read_exidx)( di, (UChar*)di->exidx_avma, di->exidx_size,
2957                               (UChar*)di->extab_avma, di->extab_size,
2958                               text_last_svma,
2959                               di->exidx_bias );
2960       }
2961 #     endif /* defined(VGA_arm) */
2962 
2963    } /* "Find interesting sections, read the symbol table(s), read any debug
2964         information" (a local scope) */
2965 
2966    /* TOPLEVEL */
2967    res = True;
2968 
2969    /* If reading Dwarf3 variable type/location info, print a line
2970       showing the number of variables read for each object.
2971       (Currently disabled -- is a sanity-check mechanism for
2972       exp-sgcheck.) */
2973    if (0 &&  VG_(clo_read_var_info)) {
2974       UWord nVars = 0;
2975       if (di->varinfo) {
2976          for (j = 0; j < VG_(sizeXA)(di->varinfo); j++) {
2977             OSet* /* of DiAddrRange */ scope
2978                = *(OSet**)VG_(indexXA)(di->varinfo, j);
2979             vg_assert(scope);
2980             VG_(OSetGen_ResetIter)( scope );
2981             while (True) {
2982                DiAddrRange* range  = VG_(OSetGen_Next)( scope );
2983                if (!range) break;
2984                vg_assert(range->vars);
2985                Word w = VG_(sizeXA)(range->vars);
2986                vg_assert(w >= 0);
2987                if (0) VG_(printf)("range %#lx %#lx %ld\n",
2988                                   range->aMin, range->aMax, w);
2989                nVars += (UWord)w;
2990             }
2991          }
2992       }
2993       VG_(umsg)("VARINFO: %7lu vars   %7ld text_size   %s\n",
2994                 nVars, di->text_size, di->fsm.filename);
2995    }
2996    /* TOPLEVEL */
2997 
2998   out:
2999    {
3000       /* Last, but not least, detach from the image(s). */
3001       if (mimg) ML_(img_done)(mimg);
3002       if (dimg) ML_(img_done)(dimg);
3003       if (aimg) ML_(img_done)(aimg);
3004 
3005       if (svma_ranges) VG_(deleteXA)(svma_ranges);
3006 
3007       return res;
3008    } /* out: */
3009 
3010    /* NOTREACHED */
3011 }
3012 
3013 #endif // defined(VGO_linux)
3014 
3015 /*--------------------------------------------------------------------*/
3016 /*--- end                                                          ---*/
3017 /*--------------------------------------------------------------------*/
3018