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