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