• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*--------------------------------------------------------------------*/
3 /*--- Reading of syms & debug info from ELF .so/executable files.  ---*/
4 /*---                                                    readelf.c ---*/
5 /*--------------------------------------------------------------------*/
6 
7 /*
8    This file is part of Valgrind, a dynamic binary instrumentation
9    framework.
10 
11    Copyright (C) 2000-2011 Julian Seward
12       jseward@acm.org
13 
14    This program is free software; you can redistribute it and/or
15    modify it under the terms of the GNU General Public License as
16    published by the Free Software Foundation; either version 2 of the
17    License, or (at your option) any later version.
18 
19    This program is distributed in the hope that it will be useful, but
20    WITHOUT ANY WARRANTY; without even the implied warranty of
21    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22    General Public License for more details.
23 
24    You should have received a copy of the GNU General Public License
25    along with this program; if not, write to the Free Software
26    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27    02111-1307, USA.
28 
29    The GNU General Public License is contained in the file COPYING.
30 */
31 
32 #if defined(VGO_linux)
33 
34 #include "pub_core_basics.h"
35 #include "pub_core_vki.h"
36 #include "pub_core_debuginfo.h"
37 #include "pub_core_libcbase.h"
38 #include "pub_core_libcprint.h"
39 #include "pub_core_libcassert.h"
40 #include "pub_core_libcfile.h"
41 #include "pub_core_aspacemgr.h"    /* for mmaping debuginfo files */
42 #include "pub_core_machine.h"      /* VG_ELF_CLASS */
43 #include "pub_core_mallocfree.h"
44 #include "pub_core_options.h"
45 #include "pub_core_oset.h"
46 #include "pub_core_tooliface.h"    /* VG_(needs) */
47 #include "pub_core_xarray.h"
48 #include "priv_misc.h"             /* dinfo_zalloc/free/strdup */
49 #include "priv_d3basics.h"
50 #include "priv_tytypes.h"
51 #include "priv_storage.h"
52 #include "priv_readelf.h"          /* self */
53 #include "priv_readdwarf.h"        /* 'cos ELF contains DWARF */
54 #include "priv_readdwarf3.h"
55 #include "priv_readstabs.h"        /* and stabs, if we're unlucky */
56 
57 /* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
58 #include <elf.h>
59 /* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
60 
61 /*------------------------------------------------------------*/
62 /*--- 32/64-bit parameterisation                           ---*/
63 /*------------------------------------------------------------*/
64 
65 /* For all the ELF macros and types which specify '32' or '64',
66    select the correct variant for this platform and give it
67    an 'XX' name.  Then use the 'XX' variant consistently in
68    the rest of this file.
69 */
70 #if VG_WORDSIZE == 4
71 #  define  ElfXX_Ehdr     Elf32_Ehdr
72 #  define  ElfXX_Shdr     Elf32_Shdr
73 #  define  ElfXX_Phdr     Elf32_Phdr
74 #  define  ElfXX_Nhdr     Elf32_Nhdr
75 #  define  ElfXX_Sym      Elf32_Sym
76 #  define  ElfXX_Off      Elf32_Off
77 #  define  ElfXX_Word     Elf32_Word
78 #  define  ElfXX_Addr     Elf32_Addr
79 #  define  ElfXX_Dyn      Elf32_Dyn
80 #  define  ELFXX_ST_BIND  ELF32_ST_BIND
81 #  define  ELFXX_ST_TYPE  ELF32_ST_TYPE
82 
83 #elif VG_WORDSIZE == 8
84 #  define  ElfXX_Ehdr     Elf64_Ehdr
85 #  define  ElfXX_Shdr     Elf64_Shdr
86 #  define  ElfXX_Phdr     Elf64_Phdr
87 #  define  ElfXX_Nhdr     Elf64_Nhdr
88 #  define  ElfXX_Sym      Elf64_Sym
89 #  define  ElfXX_Off      Elf64_Off
90 #  define  ElfXX_Word     Elf64_Word
91 #  define  ElfXX_Addr     Elf64_Addr
92 #  define  ElfXX_Dyn      Elf64_Dyn
93 #  define  ELFXX_ST_BIND  ELF64_ST_BIND
94 #  define  ELFXX_ST_TYPE  ELF64_ST_TYPE
95 
96 #else
97 # error "VG_WORDSIZE should be 4 or 8"
98 #endif
99 
100 
101 /*------------------------------------------------------------*/
102 /*---                                                      ---*/
103 /*--- Read symbol table and line info from ELF files.      ---*/
104 /*---                                                      ---*/
105 /*------------------------------------------------------------*/
106 
107 /* readelf.c parses ELF files and acquires symbol table info from
108    them.  It calls onwards to readdwarf.c to read DWARF2/3 line number
109    and call frame info found. */
110 
111 
112 /* Identify an ELF object file by peering at the first few bytes of
113    it. */
114 
ML_(is_elf_object_file)115 Bool ML_(is_elf_object_file)( void* image, SizeT n_image )
116 {
117    ElfXX_Ehdr* ehdr = (ElfXX_Ehdr*)image;
118    Int ok = 1;
119 
120    if (n_image < sizeof(ElfXX_Ehdr))
121       return False;
122 
123    ok &= (ehdr->e_ident[EI_MAG0] == 0x7F
124           && ehdr->e_ident[EI_MAG1] == 'E'
125           && ehdr->e_ident[EI_MAG2] == 'L'
126           && ehdr->e_ident[EI_MAG3] == 'F');
127    ok &= (ehdr->e_ident[EI_CLASS] == VG_ELF_CLASS
128           && ehdr->e_ident[EI_DATA] == VG_ELF_DATA2XXX
129           && ehdr->e_ident[EI_VERSION] == EV_CURRENT);
130    ok &= (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN);
131    ok &= (ehdr->e_machine == VG_ELF_MACHINE);
132    ok &= (ehdr->e_version == EV_CURRENT);
133    ok &= (ehdr->e_shstrndx != SHN_UNDEF);
134    ok &= (ehdr->e_shoff != 0 && ehdr->e_shnum != 0);
135    ok &= (ehdr->e_phoff != 0 && ehdr->e_phnum != 0);
136 
137    if (ok)
138       return True;
139    else
140       return False;
141 }
142 
143 
144 /* Show a raw ELF symbol, given its in-image address and name. */
145 
146 static
show_raw_elf_symbol(Int i,ElfXX_Sym * sym,Char * sym_name,Addr sym_svma,Bool ppc64_linux_format)147 void show_raw_elf_symbol ( Int i,
148                            ElfXX_Sym* sym, Char* sym_name, Addr sym_svma,
149                            Bool ppc64_linux_format )
150 {
151    HChar* space = ppc64_linux_format ? "                  " : "";
152    VG_(printf)("raw symbol [%4d]: ", i);
153    switch (ELFXX_ST_BIND(sym->st_info)) {
154       case STB_LOCAL:  VG_(printf)("LOC "); break;
155       case STB_GLOBAL: VG_(printf)("GLO "); break;
156       case STB_WEAK:   VG_(printf)("WEA "); break;
157       case STB_LOPROC: VG_(printf)("lop "); break;
158       case STB_HIPROC: VG_(printf)("hip "); break;
159       default:         VG_(printf)("??? "); break;
160    }
161    switch (ELFXX_ST_TYPE(sym->st_info)) {
162       case STT_NOTYPE:  VG_(printf)("NOT "); break;
163       case STT_OBJECT:  VG_(printf)("OBJ "); break;
164       case STT_FUNC:    VG_(printf)("FUN "); break;
165       case STT_SECTION: VG_(printf)("SEC "); break;
166       case STT_FILE:    VG_(printf)("FIL "); break;
167       case STT_LOPROC:  VG_(printf)("lop "); break;
168       case STT_HIPROC:  VG_(printf)("hip "); break;
169       default:          VG_(printf)("??? "); break;
170    }
171    VG_(printf)(": svma %#010lx, %ssz %4ld  %s\n",
172                sym_svma, space, sym->st_size + 0UL,
173                ( sym->st_name ? sym_name : (Char*)"NONAME" ) );
174 }
175 
176 
177 /* Decide whether SYM is something we should collect, and if so, copy
178    relevant info to the _OUT arguments.  For {x86,amd64,ppc32}-linux
179    this is straightforward - the name, address, size are copied out
180    unchanged.
181 
182    There is a bit of a kludge re data symbols (see KLUDGED BSS CHECK
183    below): we assume that the .bss is mapped immediately after .data,
184    and so accept any data symbol which exists in the range [start of
185    .data, size of .data + size of .bss).  I don't know if this is
186    really correct/justifiable, or not.
187 
188    For ppc64-linux it's more complex.  If the symbol is seen to be in
189    the .opd section, it is taken to be a function descriptor, and so
190    a dereference is attempted, in order to get hold of the real entry
191    point address.  Also as part of the dereference, there is an attempt
192    to calculate the TOC pointer (R2 value) associated with the symbol.
193 
194    To support the ppc64-linux pre-"dotless" ABI (prior to gcc 4.0.0),
195    if the symbol is seen to be outside the .opd section and its name
196    starts with a dot, an .opd deference is not attempted, and no TOC
197    pointer is calculated, but the the leading dot is removed from the
198    name.
199 
200    As a result, on ppc64-linux, the caller of this function may have
201    to piece together the real size, address, name of the symbol from
202    multiple calls to this function.  Ugly and confusing.
203 */
204 static
get_elf_symbol_info(struct _DebugInfo * di,ElfXX_Sym * sym,Char * sym_name,Addr sym_svma,Bool symtab_in_debug,UChar * opd_img,PtrdiffT opd_bias,Char ** sym_name_out,Addr * sym_avma_out,Int * sym_size_out,Addr * sym_tocptr_out,Bool * from_opd_out,Bool * is_text_out,Bool * is_ifunc)205 Bool get_elf_symbol_info (
206         /* INPUTS */
207         struct _DebugInfo* di, /* containing DebugInfo */
208         ElfXX_Sym* sym,        /* ELF symbol */
209         Char*      sym_name,   /* name */
210         Addr       sym_svma,   /* address as stated in the object file */
211         Bool       symtab_in_debug, /* symbol table is in the debug file */
212         UChar*     opd_img,    /* oimage of .opd sec (ppc64-linux only) */
213         PtrdiffT   opd_bias,   /* for biasing AVMAs found in .opd */
214         /* OUTPUTS */
215         Char** sym_name_out,   /* name we should record */
216         Addr*  sym_avma_out,   /* addr we should record */
217         Int*   sym_size_out,   /* symbol size */
218         Addr*  sym_tocptr_out, /* ppc64-linux only: R2 value to be
219                                   used on entry */
220         Bool*  from_opd_out,   /* ppc64-linux only: did we deref an
221                                   .opd entry? */
222         Bool*  is_text_out,    /* is this a text symbol? */
223         Bool*  is_ifunc        /* is this a  STT_GNU_IFUNC function ?*/
224      )
225 {
226    Bool plausible;
227 #  if defined(VGP_ppc64_linux)
228    Bool is_in_opd;
229 #  endif
230    Bool in_text, in_data, in_sdata, in_rodata, in_bss, in_sbss;
231    Addr text_svma, data_svma, sdata_svma, rodata_svma, bss_svma, sbss_svma;
232    PtrdiffT text_bias, data_bias, sdata_bias, rodata_bias, bss_bias, sbss_bias;
233 
234    /* Set defaults */
235    *sym_name_out   = sym_name;
236    *sym_avma_out   = sym_svma; /* we will bias this shortly */
237    *is_text_out    = True;
238    *sym_size_out   = (Int)sym->st_size;
239    *sym_tocptr_out = 0; /* unknown/inapplicable */
240    *from_opd_out   = False;
241    *is_ifunc       = False;
242 
243    /* Figure out if we're interested in the symbol.  Firstly, is it of
244       the right flavour?  */
245    plausible
246       = (ELFXX_ST_BIND(sym->st_info) == STB_GLOBAL
247          || ELFXX_ST_BIND(sym->st_info) == STB_LOCAL
248          || ELFXX_ST_BIND(sym->st_info) == STB_WEAK
249         )
250         &&
251         (ELFXX_ST_TYPE(sym->st_info) == STT_FUNC
252          || ELFXX_ST_TYPE(sym->st_info) == STT_OBJECT
253 #ifdef STT_GNU_IFUNC
254          || ELFXX_ST_TYPE(sym->st_info) == STT_GNU_IFUNC
255 #endif
256         );
257 
258    /* Work out the svma and bias for each section as it will appear in
259       addresses in the symbol table. */
260    if (symtab_in_debug) {
261       text_svma = di->text_debug_svma;
262       text_bias = di->text_debug_bias;
263       data_svma = di->data_debug_svma;
264       data_bias = di->data_debug_bias;
265       sdata_svma = di->sdata_debug_svma;
266       sdata_bias = di->sdata_debug_bias;
267       rodata_svma = di->rodata_debug_svma;
268       rodata_bias = di->rodata_debug_bias;
269       bss_svma = di->bss_debug_svma;
270       bss_bias = di->bss_debug_bias;
271       sbss_svma = di->sbss_debug_svma;
272       sbss_bias = di->sbss_debug_bias;
273    } else {
274       text_svma = di->text_svma;
275       text_bias = di->text_bias;
276       data_svma = di->data_svma;
277       data_bias = di->data_bias;
278       sdata_svma = di->sdata_svma;
279       sdata_bias = di->sdata_bias;
280       rodata_svma = di->rodata_svma;
281       rodata_bias = di->rodata_bias;
282       bss_svma = di->bss_svma;
283       bss_bias = di->bss_bias;
284       sbss_svma = di->sbss_svma;
285       sbss_bias = di->sbss_bias;
286    }
287 
288    /* Now bias sym_avma_out accordingly by figuring out exactly which
289       section the symbol is from and bias accordingly.  Screws up if
290       the previously deduced section svma address ranges are wrong. */
291    if (di->text_present
292        && di->text_size > 0
293        && sym_svma >= text_svma
294        && sym_svma < text_svma + di->text_size) {
295       *is_text_out = True;
296       *sym_avma_out += text_bias;
297    } else
298    if (di->data_present
299        && di->data_size > 0
300        && sym_svma >= data_svma
301        && sym_svma < data_svma + di->data_size) {
302       *is_text_out = False;
303       *sym_avma_out += data_bias;
304    } else
305    if (di->sdata_present
306        && di->sdata_size > 0
307        && sym_svma >= sdata_svma
308        && sym_svma < sdata_svma + di->sdata_size) {
309       *is_text_out = False;
310       *sym_avma_out += sdata_bias;
311    } else
312    if (di->rodata_present
313        && di->rodata_size > 0
314        && sym_svma >= rodata_svma
315        && sym_svma < rodata_svma + di->rodata_size) {
316       *is_text_out = False;
317       *sym_avma_out += rodata_bias;
318    } else
319    if (di->bss_present
320        && di->bss_size > 0
321        && sym_svma >= bss_svma
322        && sym_svma < bss_svma + di->bss_size) {
323       *is_text_out = False;
324       *sym_avma_out += bss_bias;
325    } else
326    if (di->sbss_present
327        && di->sbss_size > 0
328        && sym_svma >= sbss_svma
329        && sym_svma < sbss_svma + di->sbss_size) {
330       *is_text_out = False;
331       *sym_avma_out += sbss_bias;
332    } else {
333       /* Assume it's in .text.  Is this a good idea? */
334       *is_text_out = True;
335       *sym_avma_out += text_bias;
336    }
337 
338 #  ifdef STT_GNU_IFUNC
339    /* Check for indirect functions. */
340    if (*is_text_out
341        && ELFXX_ST_TYPE(sym->st_info) == STT_GNU_IFUNC) {
342        *is_ifunc = True;
343    }
344 #  endif
345 
346 #  if defined(VGP_ppc64_linux)
347    /* Allow STT_NOTYPE in the very special case where we're running on
348       ppc64-linux and the symbol is one which the .opd-chasing hack
349       below will chase. */
350    if (!plausible
351        && *is_text_out
352        && ELFXX_ST_TYPE(sym->st_info) == STT_NOTYPE
353        && sym->st_size > 0
354        && di->opd_present
355        && di->opd_size > 0
356        && *sym_avma_out >= di->opd_avma
357        && *sym_avma_out <  di->opd_avma + di->opd_size)
358       plausible = True;
359 #  endif
360 
361    if (!plausible)
362       return False;
363 
364    /* Ignore if nameless. */
365    if (sym_name == (ElfXX_Word)0
366        || /* VG_(strlen)(sym_name) == 0 */
367           /* equivalent but cheaper ... */
368           sym_name[0] == 0) {
369       TRACE_SYMTAB("    ignore -- nameless: %s\n", sym_name);
370       return False;
371    }
372 
373    /* Ignore if zero-sized.  Except on Android:
374 
375       On Android 2.3.5, some of the symbols that Memcheck needs to
376       intercept (for noise reduction purposes) have zero size, due to
377       lack of .size directives in handwritten assembly sources.  So we
378       can't reject them out of hand -- instead give them a bogusly
379       large size and let canonicaliseSymtab trim them so they don't
380       overlap any following symbols.  At least the following symbols
381       are known to be affected:
382 
383       in /system/lib/libc.so: strlen strcmp strcpy memcmp memcpy
384       in /system/bin/linker:  __dl_strcmp __dl_strlen
385    */
386    if (sym->st_size == 0) {
387 #     if defined(VGPV_arm_linux_android)
388       *sym_size_out = 1024;
389 #     else
390       TRACE_SYMTAB("    ignore -- size=0: %s\n", sym_name);
391       return False;
392 #     endif
393    }
394 
395    /* This seems to significantly reduce the number of junk
396       symbols, and particularly reduces the number of
397       overlapping address ranges.  Don't ask me why ... */
398    if ((Int)sym->st_value == 0) {
399       TRACE_SYMTAB( "    ignore -- valu=0: %s\n", sym_name);
400       return False;
401    }
402 
403    /* If it's apparently in a GOT or PLT, it's really a reference to a
404       symbol defined elsewhere, so ignore it. */
405    if (di->got_present
406        && di->got_size > 0
407        && *sym_avma_out >= di->got_avma
408        && *sym_avma_out <  di->got_avma + di->got_size) {
409       TRACE_SYMTAB("    ignore -- in GOT: %s\n", sym_name);
410       return False;
411    }
412    if (di->plt_present
413        && di->plt_size > 0
414        && *sym_avma_out >= di->plt_avma
415        && *sym_avma_out <  di->plt_avma + di->plt_size) {
416       TRACE_SYMTAB("    ignore -- in PLT: %s\n", sym_name);
417       return False;
418    }
419 
420    /* ppc64-linux nasty hack: if the symbol is in an .opd section,
421       then really what we have is the address of a function
422       descriptor.  So use the first word of that as the function's
423       text.
424 
425       See thread starting at
426       http://gcc.gnu.org/ml/gcc-patches/2004-08/msg00557.html
427    */
428 #  if defined(VGP_ppc64_linux)
429    is_in_opd = False;
430 #  endif
431 
432    if (di->opd_present
433        && di->opd_size > 0
434        && *sym_avma_out >= di->opd_avma
435        && *sym_avma_out <  di->opd_avma + di->opd_size) {
436 #     if !defined(VGP_ppc64_linux)
437       TRACE_SYMTAB("    ignore -- in OPD: %s\n", sym_name);
438       return False;
439 #     else
440       Int    offset_in_opd;
441       ULong* fn_descr;
442       Bool   details = 1||False;
443 
444       if (details)
445          TRACE_SYMTAB("opdXXX: opd_bias %p, sym_svma_out %p\n",
446                       (void*)(opd_bias), (void*)*sym_avma_out);
447 
448       if (!VG_IS_8_ALIGNED(*sym_avma_out)) {
449          TRACE_SYMTAB("    ignore -- not 8-aligned: %s\n", sym_name);
450          return False;
451       }
452 
453       /* *sym_avma_out is a vma pointing into the .opd section.  We
454          know the vma of the opd section start, so we can figure out
455          how far into the opd section this is. */
456 
457       offset_in_opd = (Addr)(*sym_avma_out) - (Addr)(di->opd_avma);
458       if (offset_in_opd < 0 || offset_in_opd >= di->opd_size) {
459          TRACE_SYMTAB("    ignore -- invalid OPD offset: %s\n", sym_name);
460          return False;
461       }
462 
463       /* Now we want to know what's at that offset in the .opd
464          section.  We can't look in the running image since it won't
465          necessarily have been mapped.  But we can consult the oimage.
466          opd_img is the start address of the .opd in the oimage.
467          Hence: */
468 
469       fn_descr = (ULong*)(opd_img + offset_in_opd);
470 
471       if (details)
472          TRACE_SYMTAB("opdXXY: offset %d,  fn_descr %p\n",
473                       offset_in_opd, fn_descr);
474       if (details)
475          TRACE_SYMTAB("opdXXZ: *fn_descr %p\n", (void*)(fn_descr[0]));
476 
477       /* opd_bias is the what we have to add to SVMAs found in .opd to
478          get plausible .text AVMAs for the entry point, and .data
479          AVMAs (presumably) for the TOC locations.  We use the caller
480          supplied value (which is di->text_bias) for both of these.
481          Not sure why that is correct - it seems to work, and sounds
482          OK for fn_descr[0], but surely we need to use the data bias
483          and not the text bias for fn_descr[1] ?  Oh Well.
484       */
485       *sym_avma_out   = fn_descr[0] + opd_bias;
486       *sym_tocptr_out = fn_descr[1] + opd_bias;
487       *from_opd_out   = True;
488       is_in_opd = True;
489 
490       /* Do a final sanity check: if the symbol falls outside the
491          DebugInfo's mapped range, ignore it.  Since *sym_avma_out has
492          been updated, that can be achieved simply by falling through
493          to the test below. */
494 
495 #     endif /* ppc64-linux nasty hack */
496    }
497 
498    /* Here's yet another ppc64-linux hack.  Get rid of leading dot if
499       the symbol is outside .opd. */
500 #  if defined(VGP_ppc64_linux)
501    if (di->opd_size > 0
502        && !is_in_opd
503        && sym_name[0] == '.') {
504       vg_assert(!(*from_opd_out));
505       *sym_name_out = &sym_name[1];
506    }
507 #  endif
508 
509    /* If no part of the symbol falls within the mapped range,
510       ignore it. */
511 
512    in_text
513       = di->text_present
514         && di->text_size > 0
515         && !(*sym_avma_out + *sym_size_out <= di->text_avma
516              || *sym_avma_out >= di->text_avma + di->text_size);
517 
518    in_data
519       = di->data_present
520         && di->data_size > 0
521         && !(*sym_avma_out + *sym_size_out <= di->data_avma
522              || *sym_avma_out >= di->data_avma + di->data_size);
523 
524    in_sdata
525       = di->sdata_present
526         && di->sdata_size > 0
527         && !(*sym_avma_out + *sym_size_out <= di->sdata_avma
528              || *sym_avma_out >= di->sdata_avma + di->sdata_size);
529 
530    in_rodata
531       = di->rodata_present
532         && di->rodata_size > 0
533         && !(*sym_avma_out + *sym_size_out <= di->rodata_avma
534              || *sym_avma_out >= di->rodata_avma + di->rodata_size);
535 
536    in_bss
537       = di->bss_present
538         && di->bss_size > 0
539         && !(*sym_avma_out + *sym_size_out <= di->bss_avma
540              || *sym_avma_out >= di->bss_avma + di->bss_size);
541 
542    in_sbss
543       = di->sbss_present
544         && di->sbss_size > 0
545         && !(*sym_avma_out + *sym_size_out <= di->sbss_avma
546              || *sym_avma_out >= di->sbss_avma + di->sbss_size);
547 
548 
549    if (*is_text_out) {
550       /* This used to reject any symbol falling outside the text
551          segment ("if (!in_text) ...").  Now it is relaxed slightly,
552          to reject only symbols which fall outside the area mapped
553          r-x.  This is in accordance with r7427.  See
554          "Comment_Regarding_Text_Range_Checks" in storage.c for
555          background. */
556       Bool in_rx;
557       vg_assert(di->fsm.have_rx_map);
558       in_rx = (!(*sym_avma_out + *sym_size_out <= di->fsm.rx_map_avma
559                  || *sym_avma_out >= di->fsm.rx_map_avma
560                                      + di->fsm.rx_map_size));
561       if (in_text)
562          vg_assert(in_rx);
563       if (!in_rx) {
564          TRACE_SYMTAB(
565             "ignore -- %#lx .. %#lx outside .text svma range %#lx .. %#lx\n",
566             *sym_avma_out, *sym_avma_out + *sym_size_out,
567             di->text_avma,
568             di->text_avma + di->text_size);
569          return False;
570       }
571    } else {
572      if (!(in_data || in_sdata || in_rodata || in_bss || in_sbss)) {
573          TRACE_SYMTAB(
574             "ignore -- %#lx .. %#lx outside .data / .sdata / .rodata "
575             "/ .bss / .sbss svma ranges\n",
576             *sym_avma_out, *sym_avma_out + *sym_size_out);
577          return False;
578       }
579    }
580 
581 #  if defined(VGP_ppc64_linux)
582    /* It's crucial that we never add symbol addresses in the .opd
583       section.  This would completely mess up function redirection and
584       intercepting.  This assert ensures that anysymbols that make it
585       into the symbol table on ppc64-linux don't point into .opd. */
586    if (di->opd_present && di->opd_size > 0) {
587       vg_assert(*sym_avma_out + *sym_size_out <= di->opd_avma
588                 || *sym_avma_out >= di->opd_avma + di->opd_size);
589    }
590 #  endif
591 
592    /* Acquire! */
593    return True;
594 }
595 
596 
597 /* Read an ELF symbol table (normal or dynamic).  This one is for the
598    "normal" case ({x86,amd64,ppc32}-linux). */
599 static
600 __attribute__((unused)) /* not referred to on all targets */
read_elf_symtab__normal(struct _DebugInfo * di,UChar * tab_name,ElfXX_Sym * symtab_img,SizeT symtab_szB,UChar * strtab_img,SizeT strtab_szB,Bool symtab_in_debug,UChar * opd_img)601 void read_elf_symtab__normal(
602         struct _DebugInfo* di, UChar* tab_name,
603         ElfXX_Sym* symtab_img, SizeT symtab_szB,
604         UChar*     strtab_img, SizeT strtab_szB,
605         Bool       symtab_in_debug,
606         UChar*     opd_img /* ppc64-linux only */
607      )
608 {
609    Word       i;
610    Addr       sym_svma, sym_avma_really;
611    Char      *sym_name, *sym_name_really;
612    Int        sym_size;
613    Addr       sym_tocptr;
614    Bool       from_opd, is_text, is_ifunc;
615    DiSym      disym;
616    ElfXX_Sym *sym;
617 
618    if (strtab_img == NULL || symtab_img == NULL) {
619       Char buf[80];
620       vg_assert(VG_(strlen)(tab_name) < 40);
621       VG_(sprintf)(buf, "   object doesn't have a %s", tab_name);
622       ML_(symerr)(di, False, buf);
623       return;
624    }
625 
626    TRACE_SYMTAB("\n--- Reading (ELF, standard) %s (%ld entries) ---\n",
627                 tab_name, symtab_szB/sizeof(ElfXX_Sym) );
628 
629    /* Perhaps should start at i = 1; ELF docs suggest that entry
630       0 always denotes 'unknown symbol'. */
631    for (i = 1; i < (Word)(symtab_szB/sizeof(ElfXX_Sym)); i++) {
632       sym      = & symtab_img[i];
633       sym_name = (UChar*)(strtab_img + sym->st_name);
634       sym_svma = sym->st_value;
635 
636       if (di->trace_symtab)
637          show_raw_elf_symbol(i, sym, sym_name, sym_svma, False);
638 
639       if (get_elf_symbol_info(di, sym, sym_name, sym_svma,
640                               symtab_in_debug,
641                               opd_img, di->text_bias,
642                               &sym_name_really,
643                               &sym_avma_really,
644                               &sym_size,
645                               &sym_tocptr,
646                               &from_opd, &is_text, &is_ifunc)) {
647 
648          disym.addr      = sym_avma_really;
649          disym.tocptr    = sym_tocptr;
650          disym.pri_name  = ML_(addStr) ( di, sym_name_really, -1 );
651          disym.sec_names = NULL;
652          disym.size      = sym_size;
653          disym.isText    = is_text;
654          disym.isIFunc   = is_ifunc;
655          vg_assert(disym.pri_name);
656          vg_assert(disym.tocptr == 0); /* has no role except on ppc64-linux */
657          ML_(addSym) ( di, &disym );
658 
659          if (di->trace_symtab) {
660             VG_(printf)("    rec(%c) [%4ld]:          "
661                         "  val %#010lx, sz %4d  %s\n",
662                         is_text ? 't' : 'd',
663                         i,
664                         disym.addr,
665                         (Int)disym.size,
666                         (HChar*)disym.pri_name
667             );
668          }
669 
670       }
671    }
672 }
673 
674 
675 /* Read an ELF symbol table (normal or dynamic).  This one is for
676    ppc64-linux, which requires special treatment. */
677 
678 typedef
679    struct {
680       Addr   addr;
681       UChar* name;
682    }
683    TempSymKey;
684 
685 typedef
686    struct {
687       TempSymKey key;
688       Addr       tocptr;
689       Int        size;
690       Bool       from_opd;
691       Bool       is_text;
692       Bool       is_ifunc;
693    }
694    TempSym;
695 
cmp_TempSymKey(TempSymKey * key1,TempSym * elem2)696 static Word cmp_TempSymKey ( TempSymKey* key1, TempSym* elem2 ) {
697    if (key1->addr < elem2->key.addr) return -1;
698    if (key1->addr > elem2->key.addr) return 1;
699    return (Word)VG_(strcmp)(key1->name, elem2->key.name);
700 }
701 
702 static
703 __attribute__((unused)) /* not referred to on all targets */
read_elf_symtab__ppc64_linux(struct _DebugInfo * di,UChar * tab_name,ElfXX_Sym * symtab_img,SizeT symtab_szB,UChar * strtab_img,SizeT strtab_szB,Bool symtab_in_debug,UChar * opd_img)704 void read_elf_symtab__ppc64_linux(
705         struct _DebugInfo* di, UChar* tab_name,
706         ElfXX_Sym* symtab_img, SizeT symtab_szB,
707         UChar*     strtab_img, SizeT strtab_szB,
708         Bool       symtab_in_debug,
709         UChar*     opd_img /* ppc64-linux only */
710      )
711 {
712    Word        i;
713    Int         old_size;
714    Addr        sym_svma, sym_avma_really;
715    Char       *sym_name, *sym_name_really;
716    Int         sym_size;
717    Addr        sym_tocptr;
718    Bool        from_opd, modify_size, modify_tocptr, is_text, is_ifunc;
719    DiSym       disym;
720    ElfXX_Sym  *sym;
721    OSet       *oset;
722    TempSymKey  key;
723    TempSym    *elem;
724    TempSym    *prev;
725 
726    if (strtab_img == NULL || symtab_img == NULL) {
727       Char buf[80];
728       vg_assert(VG_(strlen)(tab_name) < 40);
729       VG_(sprintf)(buf, "   object doesn't have a %s", tab_name);
730       ML_(symerr)(di, False, buf);
731       return;
732    }
733 
734    TRACE_SYMTAB("\n--- Reading (ELF, ppc64-linux) %s (%ld entries) ---\n",
735                 tab_name, symtab_szB/sizeof(ElfXX_Sym) );
736 
737    oset = VG_(OSetGen_Create)( offsetof(TempSym,key),
738                                (OSetCmp_t)cmp_TempSymKey,
739                                ML_(dinfo_zalloc), "di.respl.1",
740                                ML_(dinfo_free) );
741    vg_assert(oset);
742 
743    /* Perhaps should start at i = 1; ELF docs suggest that entry
744       0 always denotes 'unknown symbol'. */
745    for (i = 1; i < (Word)(symtab_szB/sizeof(ElfXX_Sym)); i++) {
746       sym      = & symtab_img[i];
747       sym_name = (Char*)(strtab_img + sym->st_name);
748       sym_svma = sym->st_value;
749 
750       if (di->trace_symtab)
751          show_raw_elf_symbol(i, sym, sym_name, sym_svma, True);
752 
753       if (get_elf_symbol_info(di, sym, sym_name, sym_svma,
754                               symtab_in_debug,
755                               opd_img, di->text_bias,
756                               &sym_name_really,
757                               &sym_avma_really,
758                               &sym_size,
759                               &sym_tocptr,
760                               &from_opd, &is_text, &is_ifunc)) {
761 
762          /* Check if we've seen this (name,addr) key before. */
763          key.addr = sym_avma_really;
764          key.name = sym_name_really;
765          prev = VG_(OSetGen_Lookup)( oset, &key );
766 
767          if (prev) {
768 
769             /* Seen it before.  Fold in whatever new info we can. */
770             modify_size   = False;
771             modify_tocptr = False;
772             old_size   = 0;
773 
774             if (prev->from_opd && !from_opd
775                 && (prev->size == 24 || prev->size == 16)
776                 && sym_size != prev->size) {
777                /* Existing one is an opd-redirect, with a bogus size,
778                   so the only useful new fact we have is the real size
779                   of the symbol. */
780                modify_size = True;
781                old_size = prev->size;
782                prev->size = sym_size;
783             }
784             else
785             if (!prev->from_opd && from_opd
786                 && (sym_size == 24 || sym_size == 16)) {
787                /* Existing one is non-opd, new one is opd.  What we
788                   can acquire from the new one is the TOC ptr to be
789                   used.  Since the existing sym is non-toc, it
790                   shouldn't currently have an known TOC ptr. */
791                vg_assert(prev->tocptr == 0);
792                modify_tocptr = True;
793                prev->tocptr = sym_tocptr;
794             }
795             else {
796                /* ignore. can we do better here? */
797             }
798 
799             /* Only one or the other is possible (I think) */
800             vg_assert(!(modify_size && modify_tocptr));
801 
802             if (modify_size && di->trace_symtab) {
803                VG_(printf)("    modify (old sz %4d)    "
804                            " val %#010lx, toc %#010lx, sz %4d  %s\n",
805                            old_size,
806                            prev->key.addr,
807                            prev->tocptr,
808                            (Int)   prev->size,
809                            (HChar*)prev->key.name
810                );
811             }
812             if (modify_tocptr && di->trace_symtab) {
813                VG_(printf)("    modify (upd tocptr)     "
814                            " val %#010lx, toc %#010lx, sz %4d  %s\n",
815                            prev->key.addr,
816                            prev->tocptr,
817                            (Int)   prev->size,
818                            (HChar*)prev->key.name
819                );
820             }
821 
822          } else {
823 
824             /* A new (name,addr) key.  Add and continue. */
825             elem = VG_(OSetGen_AllocNode)(oset, sizeof(TempSym));
826             vg_assert(elem);
827             elem->key      = key;
828             elem->tocptr   = sym_tocptr;
829             elem->size     = sym_size;
830             elem->from_opd = from_opd;
831             elem->is_text  = is_text;
832             elem->is_ifunc = is_ifunc;
833             VG_(OSetGen_Insert)(oset, elem);
834             if (di->trace_symtab) {
835                VG_(printf)("   to-oset [%4ld]:          "
836                            "  val %#010lx, toc %#010lx, sz %4d  %s\n",
837                            i,
838                            elem->key.addr,
839                            elem->tocptr,
840                            (Int)   elem->size,
841                            (HChar*)elem->key.name
842                );
843             }
844 
845          }
846       }
847    }
848 
849    /* All the syms that matter are in the oset.  Now pull them out,
850       build a "standard" symbol table, and nuke the oset. */
851 
852    i = 0;
853    VG_(OSetGen_ResetIter)( oset );
854 
855    while ( (elem = VG_(OSetGen_Next)(oset)) ) {
856       disym.addr      = elem->key.addr;
857       disym.tocptr    = elem->tocptr;
858       disym.pri_name  = ML_(addStr) ( di, elem->key.name, -1 );
859       disym.sec_names = NULL;
860       disym.size      = elem->size;
861       disym.isText    = elem->is_text;
862       disym.isIFunc   = elem->is_ifunc;
863       vg_assert(disym.pri_name != NULL);
864 
865       ML_(addSym) ( di, &disym );
866       if (di->trace_symtab) {
867          VG_(printf)("    rec(%c) [%4ld]:          "
868                      "   val %#010lx, toc %#010lx, sz %4d  %s\n",
869                      disym.isText ? 't' : 'd',
870                      i,
871                      disym.addr,
872                      disym.tocptr,
873                      (Int)   disym.size,
874                      (HChar*)disym.pri_name
875                );
876       }
877       i++;
878    }
879 
880    VG_(OSetGen_Destroy)( oset );
881 }
882 
883 
884 /*
885  * Look for a build-id in an ELF image. The build-id specification
886  * can be found here:
887  *
888  * http://fedoraproject.org/wiki/RolandMcGrath/BuildID
889  */
890 static
find_buildid(Addr image,UWord n_image)891 Char *find_buildid(Addr image, UWord n_image)
892 {
893    Char* buildid = NULL;
894    __attribute__((unused)) /* on Android, at least */
895    ElfXX_Ehdr* ehdr = (ElfXX_Ehdr*)image;
896 
897 #ifdef NT_GNU_BUILD_ID
898    if (n_image >= sizeof(ElfXX_Ehdr) &&
899        ML_(is_elf_object_file)(ehdr, n_image)) {
900       Word i;
901 
902       for (i = 0; i < ehdr->e_phnum; i++) {
903          ElfXX_Phdr* phdr
904             = (ElfXX_Phdr*)(image + ehdr->e_phoff + i * ehdr->e_phentsize);
905 
906          if (phdr->p_type == PT_NOTE) {
907             ElfXX_Off offset =  phdr->p_offset;
908 
909             while (offset < phdr->p_offset + phdr->p_filesz) {
910                ElfXX_Nhdr* note = (ElfXX_Nhdr*)(image + offset);
911                Char* name = (Char *)note + sizeof(ElfXX_Nhdr);
912                UChar *desc = (UChar *)name + ((note->n_namesz + 3) & ~3);
913                Word j;
914 
915                if (VG_(strcmp)(name, ELF_NOTE_GNU) == 0 &&
916                    note->n_type == NT_GNU_BUILD_ID) {
917                   buildid = ML_(dinfo_zalloc)("di.fbi.1",
918                                               note->n_descsz * 2 + 1);
919 
920                   for (j = 0; j < note->n_descsz; j++) {
921                      VG_(sprintf)(buildid + VG_(strlen)(buildid),
922                                   "%02x", desc[j]);
923                   }
924                }
925 
926                offset = offset + sizeof(ElfXX_Nhdr)
927                                + ((note->n_namesz + 3) & ~3)
928                                + ((note->n_descsz + 3) & ~3);
929             }
930          }
931       }
932    }
933 #endif
934 
935    return buildid;
936 }
937 
938 /*
939  * This routine for calculating the CRC for a separate debug file
940  * is GPLed code borrowed from GNU binutils.
941  */
942 static UInt
calc_gnu_debuglink_crc32(UInt crc,const UChar * buf,Int len)943 calc_gnu_debuglink_crc32(UInt crc, const UChar *buf, Int len)
944 {
945   static const UInt crc32_table[256] =
946     {
947       0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
948       0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
949       0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
950       0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
951       0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
952       0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
953       0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
954       0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
955       0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
956       0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
957       0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
958       0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
959       0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
960       0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
961       0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
962       0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
963       0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
964       0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
965       0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
966       0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
967       0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
968       0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
969       0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
970       0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
971       0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
972       0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
973       0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
974       0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
975       0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
976       0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
977       0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
978       0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
979       0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
980       0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
981       0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
982       0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
983       0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
984       0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
985       0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
986       0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
987       0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
988       0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
989       0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
990       0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
991       0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
992       0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
993       0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
994       0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
995       0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
996       0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
997       0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
998       0x2d02ef8d
999     };
1000   const UChar *end;
1001 
1002   crc = ~crc & 0xffffffff;
1003   for (end = buf + len; buf < end; ++ buf)
1004     crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);
1005   return ~crc & 0xffffffff;;
1006 }
1007 
1008 /*
1009  * Try and open a separate debug file, ignoring any where the CRC does
1010  * not match the value from the main object file.
1011  */
1012 static
open_debug_file(Char * name,Char * buildid,UInt crc,UWord * size)1013 Addr open_debug_file( Char* name, Char* buildid, UInt crc, /*OUT*/UWord* size )
1014 {
1015    SysRes fd, sres;
1016    struct vg_stat stat_buf;
1017    UInt calccrc;
1018 
1019    fd = VG_(open)(name, VKI_O_RDONLY, 0);
1020    if (sr_isError(fd))
1021       return 0;
1022 
1023    if (VG_(fstat)(sr_Res(fd), &stat_buf) != 0) {
1024       VG_(close)(sr_Res(fd));
1025       return 0;
1026    }
1027 
1028    if (VG_(clo_verbosity) > 1)
1029       VG_(message)(Vg_DebugMsg, "  Considering %s ..\n", name);
1030 
1031    *size = stat_buf.size;
1032 
1033    sres = VG_(am_mmap_file_float_valgrind)
1034              ( *size, VKI_PROT_READ, sr_Res(fd), 0 );
1035 
1036    VG_(close)(sr_Res(fd));
1037 
1038    if (sr_isError(sres))
1039       return 0;
1040 
1041    if (buildid) {
1042       Char* debug_buildid = find_buildid(sr_Res(sres), *size);
1043       if (debug_buildid == NULL || VG_(strcmp)(buildid, debug_buildid) != 0) {
1044          SysRes res = VG_(am_munmap_valgrind)(sr_Res(sres), *size);
1045          vg_assert(!sr_isError(res));
1046          if (VG_(clo_verbosity) > 1)
1047             VG_(message)(Vg_DebugMsg,
1048                "  .. build-id mismatch (found %s wanted %s)\n",
1049                debug_buildid, buildid);
1050          ML_(dinfo_free)(debug_buildid);
1051          return 0;
1052       }
1053       ML_(dinfo_free)(debug_buildid);
1054 
1055       if (VG_(clo_verbosity) > 1)
1056          VG_(message)(Vg_DebugMsg, "  .. build-id is valid\n");
1057    } else {
1058       calccrc = calc_gnu_debuglink_crc32(0, (UChar*)sr_Res(sres), *size);
1059       if (calccrc != crc) {
1060          SysRes res = VG_(am_munmap_valgrind)(sr_Res(sres), *size);
1061          vg_assert(!sr_isError(res));
1062          if (VG_(clo_verbosity) > 1)
1063             VG_(message)(Vg_DebugMsg,
1064                "  .. CRC mismatch (computed %08x wanted %08x)\n", calccrc, crc);
1065          return 0;
1066       }
1067 
1068       if (VG_(clo_verbosity) > 1)
1069          VG_(message)(Vg_DebugMsg, "  .. CRC is valid\n");
1070    }
1071 
1072    return sr_Res(sres);
1073 }
1074 
1075 
1076 /* Try to find and map in a debuginfo file by some totally ad-hoc
1077    scheme.  If successful, set *dimage and *n_dimage to point to the
1078    image, and return True, else return False.  A temporary hack for
1079    Android; does nothing on any other platform. */
1080 static
find_ad_hoc_debug_image(struct _DebugInfo * di,Char * filename,Addr * dimage,SizeT * n_dimage)1081 Bool find_ad_hoc_debug_image( struct _DebugInfo* di,
1082                               Char* filename,
1083                               /*OUT*/Addr* dimage,
1084                               /*OUT*/SizeT* n_dimage )
1085 {
1086    vg_assert(*dimage == 0 && *n_dimage == 0);
1087 
1088 #  if !defined(VGPV_arm_linux_android)
1089    return False; /* we don't know narfink */
1090 
1091 #  else /* android specific hacks; look away now. */
1092 
1093    /* The deal is: if we're looking for for a debuginfo file for some
1094       object /system/blah (where blah can be any path), see if we can
1095       find the file /sdcard/symbols/system/blah.  So for example it
1096       produces the following mappings, both of which are important for
1097       Memcheck:
1098 
1099       /system/bin/linker  --> /sdcard/symbols/system/bin/linker
1100       /system/lib/libc.so --> /sdcard/symbols/system/lib/libc.so
1101 
1102       These /symbols files come from the AOSP build tree for your
1103       device, for example out/target/product/crespo/symbols/system
1104       (for a Nexus S), so one simple thing you can do is take the tree
1105       rooted at out/target/product/crespo/symbols/system on the host
1106       and park it at /sdcard/symbols/system on the device.  Then,
1107       assuming it matches what's actually running on the device,
1108       you'll have full debuginfo for all the libraries on the device.
1109 
1110       But beware: there is no checking that the debuginfo file, if
1111       found, matches the main file in any way.
1112    */
1113    if (0 != VG_(strncmp)(filename, "/system/", 8))
1114       return False;
1115 
1116    HChar* nm = ML_(dinfo_zalloc)("di.fahdi.1",
1117                                  50 + VG_(strlen)(filename));
1118    VG_(sprintf)(nm, "/sdcard/symbols%s", filename);
1119 
1120    SysRes fd = VG_(open)(nm, VKI_O_RDONLY, 0);
1121    if (sr_isError(fd)) goto fail;
1122 
1123    struct vg_stat stat_buf;
1124    if (VG_(fstat)(sr_Res(fd), &stat_buf) != 0) {
1125       VG_(close)(sr_Res(fd));
1126       goto fail;
1127    }
1128 
1129    *n_dimage = stat_buf.size;
1130 
1131    SysRes sres = VG_(am_mmap_file_float_valgrind)
1132                     ( *n_dimage, VKI_PROT_READ, sr_Res(fd), 0 );
1133 
1134    VG_(close)(sr_Res(fd));
1135    if (sr_isError(sres))
1136      goto fail;
1137 
1138    *dimage = sr_Res(sres);
1139 
1140    if (VG_(clo_verbosity) > 1)
1141       VG_(dmsg)("  Using debuginfo from %s\n", nm);
1142 
1143    ML_(dinfo_free)(nm);
1144    return True;
1145 
1146   fail:
1147    if (nm) ML_(dinfo_free)(nm);
1148    return False;
1149 
1150 #  endif
1151 }
1152 
1153 
1154 /* Try to find a separate debug file for a given object file.  If
1155    found, it will be mapped in and the address and size returned in
1156    *dimage and *n_dimage.  If not, *dimage and *n_dimage will be
1157    unchanged.  The caller should set them to zero before the call. */
1158 static
find_debug_file(struct _DebugInfo * di,Char * objpath,Char * buildid,Char * debugname,UInt crc,Addr * dimage,SizeT * n_dimage)1159 void find_debug_file( struct _DebugInfo* di,
1160                       Char* objpath, Char* buildid,
1161                       Char* debugname, UInt crc,
1162                       /*OUT*/Addr*  dimage,
1163                       /*OUT*/SizeT* n_dimage )
1164 {
1165    Char* debugpath = NULL;
1166    Addr  addr = 0;
1167    UWord size = 0;
1168 
1169    vg_assert(*dimage == 0 && *n_dimage == 0);
1170 
1171    if (buildid != NULL) {
1172       debugpath = ML_(dinfo_zalloc)(
1173                      "di.fdf.1",
1174                      VG_(strlen)(buildid) + 33);
1175 
1176       VG_(sprintf)(debugpath, "/usr/lib/debug/.build-id/%c%c/%s.debug",
1177                    buildid[0], buildid[1], buildid + 2);
1178 
1179       if ((addr = open_debug_file(debugpath, buildid, 0, &size)) == 0) {
1180          ML_(dinfo_free)(debugpath);
1181          debugpath = NULL;
1182       }
1183    }
1184 
1185    if (addr == 0 && debugname != NULL) {
1186       Char *objdir = ML_(dinfo_strdup)("di.fdf.2", objpath);
1187       Char *objdirptr;
1188 
1189       if ((objdirptr = VG_(strrchr)(objdir, '/')) != NULL)
1190          *objdirptr = '\0';
1191 
1192       debugpath = ML_(dinfo_zalloc)(
1193                      "di.fdf.3",
1194                      VG_(strlen)(objdir) + VG_(strlen)(debugname) + 32);
1195 
1196       VG_(sprintf)(debugpath, "%s/%s", objdir, debugname);
1197 
1198       if ((addr = open_debug_file(debugpath, NULL, crc, &size)) == 0) {
1199          VG_(sprintf)(debugpath, "%s/.debug/%s", objdir, debugname);
1200          if ((addr = open_debug_file(debugpath, NULL, crc, &size)) == 0) {
1201             VG_(sprintf)(debugpath, "/usr/lib/debug%s/%s", objdir, debugname);
1202             if ((addr = open_debug_file(debugpath, NULL, crc, &size)) == 0) {
1203 #ifdef ANDROID
1204                VG_(sprintf)(debugpath, "/data/local/symbols%s/%s", objdir, debugname);
1205                addr = open_debug_file(debugpath, NULL, crc, &size);
1206 #endif
1207            }
1208 
1209          }
1210       }
1211 
1212       ML_(dinfo_free)(objdir);
1213    }
1214 
1215    if (addr > 0 && size > 0) {
1216       TRACE_SYMTAB("\n");
1217       TRACE_SYMTAB("------ Found a debuginfo file: %s\n", debugpath);
1218       *dimage = addr;
1219       *n_dimage = size;
1220    }
1221 
1222    ML_(dinfo_free)(debugpath);
1223 }
1224 
1225 
contained_within(Addr outer,UWord n_outer,Addr inner,UWord n_inner)1226 static Bool contained_within ( Addr outer, UWord n_outer,
1227                                Addr inner, UWord n_inner )
1228 {
1229    if (n_outer == 0 || n_inner == 0)
1230       return False;
1231    /* Simplistic .. assumes no wraparound (reasonably enough) */
1232    if (inner >= outer && inner+n_inner <= outer+n_outer)
1233       return True;
1234    return False;
1235 }
1236 
INDEX_BIS(void * base,Word idx,Word scale)1237 static void* INDEX_BIS ( void* base, Word idx, Word scale ) {
1238    return (void*)( ((UChar*)base) + idx * scale );
1239 }
1240 
1241 
1242 /* Find the file offset corresponding to SVMA by using the program
1243    headers.  This is taken from binutils-2.17/binutils/readelf.c
1244    offset_from_vma(). */
1245 static
file_offset_from_svma(Bool * ok,Addr svma,ElfXX_Phdr * phdr_img,Word phdr_nent,Word phdr_ent_szB)1246 Word file_offset_from_svma ( /*OUT*/Bool* ok,
1247                              Addr         svma,
1248                              ElfXX_Phdr*  phdr_img,
1249                              Word         phdr_nent,
1250                              Word         phdr_ent_szB )
1251 {
1252    Word        i;
1253    ElfXX_Phdr* seg;
1254    for (i = 0; i < phdr_nent; i++) {
1255       seg = INDEX_BIS( phdr_img, i, phdr_ent_szB );
1256       if (seg->p_type != PT_LOAD)
1257          continue;
1258       if (svma >= (seg->p_vaddr & -seg->p_align)
1259           && svma + 1 <= seg->p_vaddr + seg->p_filesz) {
1260          *ok = True;
1261          return svma - seg->p_vaddr + seg->p_offset;
1262       }
1263    }
1264    *ok = False;
1265    return 0;
1266 }
1267 
1268 
1269 /* The central function for reading ELF debug info.  For the
1270    object/exe specified by the DebugInfo, find ELF sections, then read
1271    the symbols, line number info, file name info, CFA (stack-unwind
1272    info) and anything else we want, into the tables within the
1273    supplied DebugInfo.
1274 */
1275 
1276 /* Temporarily holds information copied out of PT_LOAD entries
1277    in ML_(read_elf_debug_info. */
1278 typedef
1279    struct { Addr svma_base; Addr svma_limit; PtrdiffT bias; }
1280    RangeAndBias;
1281 
ML_(read_elf_debug_info)1282 Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di )
1283 {
1284    /* This function is long and complex.  That, and the presence of
1285       nested scopes, means it's not always easy to see which parts are
1286       in loops/conditionals and which aren't.  To make it easier to
1287       follow, points executed exactly once -- that is, those which are
1288       the top level of the function -- are marked TOPLEVEL.
1289    */
1290    /* TOPLEVEL */
1291    Bool          res, ok;
1292    SysRes        fd, sres;
1293    Word          i;
1294    Bool          dynbss_present = False;
1295    Bool          sdynbss_present = False;
1296 
1297    /* Image addresses for the ELF file we're working with. */
1298    Addr          oimage   = 0;
1299    UWord         n_oimage = 0;
1300 
1301    /* Ditto for any ELF debuginfo file that we might happen to load. */
1302    Addr          dimage   = 0;
1303    UWord         n_dimage = 0;
1304 
1305    /* ELF header for the main file.  Should == oimage since is at
1306       start of file. */
1307    ElfXX_Ehdr* ehdr_img = NULL;
1308 
1309    /* Program header table image addr, # entries, entry size */
1310    ElfXX_Phdr* phdr_img     = NULL;
1311    UWord       phdr_nent    = 0;
1312    UWord       phdr_ent_szB = 0;
1313 
1314    /* Section header image addr, # entries, entry size.  Also the
1315       associated string table. */
1316    ElfXX_Shdr* shdr_img        = NULL;
1317    UWord       shdr_nent       = 0;
1318    UWord       shdr_ent_szB    = 0;
1319    UChar*      shdr_strtab_img = NULL;
1320 
1321    /* SVMAs covered by rx and rw segments and corresponding biases.
1322       We keep separate lists of rx and rw areas.  Each can have up to
1323       N_RX_RW_AREAS entries.  Normally each object would provide just
1324       one rx and one rw area, but Mike Hommey's elfhack creates
1325       objects with two rx PT_LOAD entries, hence the generality. */
1326    const Int N_RX_RW_AREAS = 2;
1327 
1328    RangeAndBias rx[N_RX_RW_AREAS];
1329    RangeAndBias rw[N_RX_RW_AREAS];
1330    Word n_rx = 0; /* 0 .. N_RX_RW_AREAS */
1331    Word n_rw = 0; /* 0 .. N_RX_RW_AREAS */
1332    /* Pointless paranoia: */
1333    VG_(memset)( rx, 0, sizeof(rx) );
1334    VG_(memset)( rw, 0, sizeof(rw) );
1335 
1336    /* Build ID */
1337    Char* buildid = NULL;
1338 
1339    vg_assert(di);
1340    vg_assert(di->fsm.have_rx_map == True);
1341    vg_assert(di->fsm.have_rw_map == True);
1342    vg_assert(di->fsm.rx_map_size > 0);
1343    vg_assert(di->fsm.rw_map_size > 0);
1344    vg_assert(di->have_dinfo == False);
1345    vg_assert(di->fsm.filename);
1346    vg_assert(!di->symtab);
1347    vg_assert(!di->loctab);
1348    vg_assert(!di->cfsi);
1349    vg_assert(!di->cfsi_exprs);
1350    vg_assert(!di->strchunks);
1351    vg_assert(!di->soname);
1352 
1353    /* If these don't hold true, it means that m_syswrap/m_aspacemgr
1354       managed to do a mapping where the start isn't page aligned.
1355       Which sounds pretty bogus to me. */
1356    vg_assert(VG_IS_PAGE_ALIGNED(di->fsm.rx_map_avma));
1357    vg_assert(VG_IS_PAGE_ALIGNED(di->fsm.rw_map_avma));
1358 
1359    /* ----------------------------------------------------------
1360       At this point, there is very little information in the
1361       DebugInfo.  We only know that something that looks like an ELF
1362       file has been mapped rx-ishly as recorded with the di->*rx_map*
1363       fields and has also been mapped rw-ishly as recorded with the
1364       di->*rw_map* fields.  First we examine the file's ELF Program
1365       Header, and, by comparing that against the di->*r{w,x}_map*
1366       info, try to figure out the AVMAs for the sections we care
1367       about, that should have been mapped: text, data, sdata, bss,
1368       got, plt, and toc.
1369       ---------------------------------------------------------- */
1370 
1371    res = False;
1372 
1373    oimage = (Addr)NULL;
1374    if (VG_(clo_verbosity) > 1 || VG_(clo_trace_redir))
1375       VG_(message)(Vg_DebugMsg, "Reading syms from %s (%#lx)\n",
1376                                 di->fsm.filename, di->fsm.rx_map_avma );
1377 
1378    /* mmap the object image aboard, so that we can read symbols and
1379       line number info out of it.  It will be munmapped immediately
1380       thereafter; it is only aboard transiently. */
1381 
1382    fd = VG_(open)(di->fsm.filename, VKI_O_RDONLY, 0);
1383    if (sr_isError(fd)) {
1384       ML_(symerr)(di, True, "Can't open .so/.exe to read symbols?!");
1385       return False;
1386    }
1387 
1388    { Long n_oimageLL = VG_(fsize)(sr_Res(fd));
1389      if (n_oimageLL <= 0) {
1390         ML_(symerr)(di, True, "Can't stat .so/.exe (to determine its size)?!");
1391         VG_(close)(sr_Res(fd));
1392         return False;
1393      }
1394      n_oimage = (UWord)(ULong)n_oimageLL;
1395    }
1396 
1397    sres = VG_(am_mmap_file_float_valgrind)
1398              ( n_oimage, VKI_PROT_READ, sr_Res(fd), 0 );
1399 
1400    VG_(close)(sr_Res(fd));
1401 
1402    if (sr_isError(sres)) {
1403       VG_(message)(Vg_UserMsg, "warning: mmap failed on %s\n",
1404                                di->fsm.filename );
1405       VG_(message)(Vg_UserMsg, "         no symbols or debug info loaded\n" );
1406       return False;
1407    }
1408 
1409    oimage = sr_Res(sres);
1410    /* Check against wraparound.  am_mmap_file_float_valgrind should
1411       not produce a wrapped-around mapping. */
1412    vg_assert(n_oimage > 0);
1413    vg_assert(oimage + n_oimage > oimage);
1414 
1415    if (0) {
1416       VG_(printf)("read_elf_debug_info: OIMAGE = %p - %p\n",
1417                   (void*)oimage, (void*)(oimage + (UWord)n_oimage));
1418    }
1419 
1420    /* Ok, the object image is safely in oimage[0 .. n_oimage-1].  Now
1421       verify that it is a valid ELF .so or executable image. */
1422    res      = False;
1423    ok       = (n_oimage >= sizeof(ElfXX_Ehdr));
1424    ehdr_img = (ElfXX_Ehdr*)oimage;
1425 
1426    if (ok)
1427       ok &= ML_(is_elf_object_file)(ehdr_img, n_oimage);
1428 
1429    if (!ok) {
1430       ML_(symerr)(di, True, "Invalid ELF Header");
1431       goto out;
1432    }
1433 
1434    /* Find where the program and section header tables are, and give
1435       up if either is missing or outside the image (bogus). */
1436    phdr_img     = (ElfXX_Phdr*)( ((UChar*)ehdr_img) + ehdr_img->e_phoff );
1437    phdr_nent    = ehdr_img->e_phnum;
1438    phdr_ent_szB = ehdr_img->e_phentsize;
1439 
1440    shdr_img     = (ElfXX_Shdr*)( ((UChar*)ehdr_img) + ehdr_img->e_shoff );
1441    shdr_nent    = ehdr_img->e_shnum;
1442    shdr_ent_szB = ehdr_img->e_shentsize;
1443 
1444    TRACE_SYMTAB("------ Basic facts about the object ------\n");
1445    TRACE_SYMTAB("object:  img %p n_oimage %ld\n",
1446                (void*)oimage, n_oimage);
1447    TRACE_SYMTAB("phdr:    img %p nent %ld ent_szB %ld\n",
1448                phdr_img, phdr_nent, phdr_ent_szB);
1449    TRACE_SYMTAB("shdr:    img %p nent %ld ent_szB %ld\n",
1450                shdr_img, shdr_nent, shdr_ent_szB);
1451    TRACE_SYMTAB("rx_map:  avma %#lx  size %lu  foff %lu\n",
1452                 di->fsm.rx_map_avma, di->fsm.rx_map_size, di->fsm.rx_map_foff);
1453    TRACE_SYMTAB("rw_map:  avma %#lx  size %lu  foff %lu\n",
1454                 di->fsm.rw_map_avma, di->fsm.rw_map_size, di->fsm.rw_map_foff);
1455 
1456    if (phdr_nent == 0
1457        || !contained_within(
1458              oimage, n_oimage,
1459              (Addr)phdr_img, phdr_nent * phdr_ent_szB)) {
1460       ML_(symerr)(di, True, "Missing or invalid ELF Program Header Table");
1461       goto out;
1462    }
1463 
1464    if (shdr_nent == 0
1465        || !contained_within(
1466              oimage, n_oimage,
1467              (Addr)shdr_img, shdr_nent * shdr_ent_szB)) {
1468       ML_(symerr)(di, True, "Missing or invalid ELF Section Header Table");
1469       goto out;
1470    }
1471 
1472    /* Also find the section header's string table, and validate. */
1473    /* checked previously by is_elf_object_file: */
1474    vg_assert( ehdr_img->e_shstrndx != SHN_UNDEF );
1475 
1476    shdr_strtab_img
1477       = (UChar*)( ((UChar*)ehdr_img)
1478                   + shdr_img[ehdr_img->e_shstrndx].sh_offset);
1479    if (!contained_within( oimage, n_oimage,
1480                           (Addr)shdr_strtab_img,
1481                           1/*bogus, but we don't know the real size*/ )) {
1482       ML_(symerr)(di, True, "Invalid ELF Section Header String Table");
1483       goto out;
1484    }
1485 
1486    TRACE_SYMTAB("shdr:    string table at %p\n", shdr_strtab_img );
1487 
1488    /* TOPLEVEL */
1489    /* Look through the program header table, and:
1490       - copy information from suitable PT_LOAD entries into rx[] or
1491         rw[]
1492       - find (or fake up) the .soname for this object.
1493    */
1494    TRACE_SYMTAB("\n");
1495    TRACE_SYMTAB("------ Examining the program headers ------\n");
1496    vg_assert(di->soname == NULL);
1497    {
1498       /* TOPLEVEL */
1499       ElfXX_Addr prev_svma = 0;
1500 
1501       for (i = 0; i < phdr_nent; i++) {
1502          ElfXX_Phdr* phdr = INDEX_BIS( phdr_img, i, phdr_ent_szB );
1503 
1504          /* Make sure the PT_LOADable entries are in order and
1505             non-overlapping.  This in turn means the address ranges
1506             slurped into rx[] and rw[] are in order and
1507             non-overlapping. */
1508          vg_assert(n_rx >= 0 && n_rx <= N_RX_RW_AREAS);
1509          vg_assert(n_rw >= 0 && n_rw <= N_RX_RW_AREAS);
1510 
1511          if (phdr->p_type == PT_LOAD) {
1512             TRACE_SYMTAB("PT_LOAD[%ld]: p_vaddr %#lx (prev %#lx)\n",
1513                          i, (UWord)phdr->p_vaddr, (UWord)prev_svma);
1514             TRACE_SYMTAB("PT_LOAD[%ld]:   p_offset %lu, p_filesz %lu,"
1515                          " perms %c%c%c\n",
1516                          i, (UWord)phdr->p_offset, (UWord)phdr->p_filesz,
1517                          phdr->p_flags & PF_R ? 'r' : '-',
1518                          phdr->p_flags & PF_W ? 'w' : '-',
1519                          phdr->p_flags & PF_X ? 'x' : '-');
1520             if (phdr->p_vaddr < prev_svma) {
1521                ML_(symerr)(di, True,
1522                            "ELF Program Headers are not in ascending order");
1523                goto out;
1524             }
1525             prev_svma = phdr->p_vaddr;
1526             if (phdr->p_offset >= di->fsm.rx_map_foff
1527                 && phdr->p_offset < di->fsm.rx_map_foff + di->fsm.rx_map_size
1528                 && phdr->p_offset + phdr->p_filesz
1529                    <= di->fsm.rx_map_foff + di->fsm.rx_map_size
1530                 && (phdr->p_flags & (PF_R | PF_W | PF_X)) == (PF_R | PF_X)) {
1531                if (n_rx == N_RX_RW_AREAS) {
1532                   ML_(symerr)(di, True,
1533                               "N_RX_RW_AREAS is too low; "
1534                               "increase and recompile.");
1535                   goto out;
1536                }
1537                rx[n_rx].svma_base  = phdr->p_vaddr;
1538                rx[n_rx].svma_limit = phdr->p_vaddr + phdr->p_memsz;
1539                rx[n_rx].bias       = di->fsm.rx_map_avma - di->fsm.rx_map_foff
1540                                      + phdr->p_offset - phdr->p_vaddr;
1541                n_rx++;
1542                TRACE_SYMTAB("PT_LOAD[%ld]:   acquired as rx\n", i);
1543             }
1544             else
1545             if (phdr->p_offset >= di->fsm.rw_map_foff
1546                 && phdr->p_offset < di->fsm.rw_map_foff + di->fsm.rw_map_size
1547                 && phdr->p_offset + phdr->p_filesz
1548                    <= di->fsm.rw_map_foff + di->fsm.rw_map_size
1549                 && (phdr->p_flags & (PF_R | PF_W | PF_X)) == (PF_R | PF_W)) {
1550                if (n_rw == N_RX_RW_AREAS) {
1551                   ML_(symerr)(di, True,
1552                               "N_RX_RW_AREAS is too low; "
1553                               "increase and recompile.");
1554                   goto out;
1555                }
1556                rw[n_rw].svma_base  = phdr->p_vaddr;
1557                rw[n_rw].svma_limit = phdr->p_vaddr + phdr->p_memsz;
1558                rw[n_rw].bias       = di->fsm.rw_map_avma - di->fsm.rw_map_foff
1559                                      + phdr->p_offset - phdr->p_vaddr;
1560                n_rw++;
1561                TRACE_SYMTAB("PT_LOAD[%ld]:   acquired as rw\n", i);
1562             }
1563          }
1564 
1565          /* Try to get the soname.  If there isn't one, use "NONE".
1566             The seginfo needs to have some kind of soname in order to
1567             facilitate writing redirect functions, since all redirect
1568             specifications require a soname (pattern). */
1569          if (phdr->p_type == PT_DYNAMIC && di->soname == NULL) {
1570             ElfXX_Dyn* dyn_img = (ElfXX_Dyn*)( ((UChar*)ehdr_img)
1571                                                + phdr->p_offset);
1572             Word   stroff = -1;
1573             UChar* strtab = NULL;
1574             Word   j;
1575             for (j = 0; dyn_img[j].d_tag != DT_NULL; j++) {
1576                switch (dyn_img[j].d_tag) {
1577                   case DT_SONAME: {
1578                      stroff = dyn_img[j].d_un.d_val;
1579                      break;
1580                   }
1581                   case DT_STRTAB: {
1582                      Bool ok2 = False;
1583                      Word offset = file_offset_from_svma(
1584                                       &ok2,
1585                                       dyn_img[j].d_un.d_ptr,
1586                                       phdr_img,
1587                                       phdr_nent, phdr_ent_szB
1588                                    );
1589                      if (ok2 && strtab == NULL) {
1590                         vg_assert(offset >= 0 && offset <= n_oimage);
1591                         strtab = ((UChar*)ehdr_img) + offset;
1592                      }
1593                      break;
1594                   }
1595                   default:
1596                      break;
1597                }
1598             }
1599             if (stroff != -1 && strtab != NULL) {
1600                TRACE_SYMTAB("Found soname = %s\n", strtab+stroff);
1601                di->soname = ML_(dinfo_strdup)("di.redi.1", strtab+stroff);
1602             }
1603          }
1604       } /* for (i = 0; i < phdr_nent; i++) ... */
1605       /* TOPLEVEL */
1606 
1607    } /* examine the program headers (local scope) */
1608 
1609    /* TOPLEVEL */
1610 
1611    /* If, after looking at all the program headers, we still didn't
1612       find a soname, add a fake one. */
1613    if (di->soname == NULL) {
1614       TRACE_SYMTAB("No soname found; using (fake) \"NONE\"\n");
1615       di->soname = "NONE";
1616    }
1617 
1618    // NaCl nexe
1619    if (ehdr_img->e_ident[EI_OSABI] == 0x7b) {
1620      HChar* s = VG_(arena_malloc)(VG_AR_DINFO, "di.redi.1", 6 + VG_(strlen)(di->soname));
1621      VG_(strcpy)(s, "NaCl_");
1622      VG_(strcpy)(s + 5, di->soname);
1623      di->soname = s;
1624      TRACE_SYMTAB("Fixed soname = %s\n", di->soname);
1625    }
1626 
1627 
1628    vg_assert(n_rx >= 0 && n_rx <= N_RX_RW_AREAS);
1629    vg_assert(n_rw >= 0 && n_rw <= N_RX_RW_AREAS);
1630    for (i = 0; i < n_rx; i++) {
1631       vg_assert(rx[i].svma_limit != 0);
1632    }
1633    for (i = 0; i < n_rw; i++) {
1634       vg_assert(rw[i].svma_limit != 0);
1635    }
1636 
1637    /* Now read the section table. */
1638    TRACE_SYMTAB("\n");
1639    TRACE_SYMTAB("------ Examining the section headers ------\n");
1640    TRACE_SYMTAB("rx: at %#lx are mapped foffsets %ld .. %ld\n",
1641                 di->fsm.rx_map_avma,
1642                 di->fsm.rx_map_foff,
1643                 di->fsm.rx_map_foff + di->fsm.rx_map_size - 1 );
1644    for (i = 0; i < n_rx; i++) {
1645       TRACE_SYMTAB("rx[%ld]: contains svmas %#lx .. %#lx with bias %#lx\n",
1646                    i, rx[i].svma_base, rx[i].svma_limit - 1, rx[i].bias );
1647    }
1648    TRACE_SYMTAB("rw: at %#lx are mapped foffsets %ld .. %ld\n",
1649                 di->fsm.rw_map_avma,
1650                 di->fsm.rw_map_foff,
1651                 di->fsm.rw_map_foff + di->fsm.rw_map_size - 1 );
1652    for (i = 0; i < n_rw; i++) {
1653       TRACE_SYMTAB("rw[%ld]: contains svmas %#lx .. %#lx with bias %#lx\n",
1654                    i, rw[i].svma_base, rw[i].svma_limit - 1, rw[i].bias );
1655    }
1656 
1657    /* TOPLEVEL */
1658    /* Iterate over section headers */
1659    for (i = 0; i < shdr_nent; i++) {
1660       ElfXX_Shdr* shdr = INDEX_BIS( shdr_img, i, shdr_ent_szB );
1661       UChar* name = shdr_strtab_img + shdr->sh_name;
1662       Addr   svma = shdr->sh_addr;
1663       OffT   foff = shdr->sh_offset;
1664       UWord  size = shdr->sh_size;
1665       UInt   alyn = shdr->sh_addralign;
1666       Bool   bits = !(shdr->sh_type == SHT_NOBITS);
1667       /* Look through our collection of info obtained from the PT_LOAD
1668          headers, and make 'inrx' and 'inrw' point to the first entry
1669          in each that intersects 'avma'.  If in each case none is found,
1670          leave the relevant pointer at NULL. */
1671       RangeAndBias* inrx = NULL;
1672       RangeAndBias* inrw = NULL;
1673       { Word j;
1674         for (j = 0; j < n_rx; j++) {
1675            if (svma >= rx[j].svma_base && svma < rx[j].svma_limit) {
1676              inrx = &rx[j];
1677              break;
1678            }
1679         }
1680         for (j = 0; j < n_rw; j++) {
1681            if (svma >= rw[j].svma_base && svma < rw[j].svma_limit) {
1682              inrw = &rw[j];
1683              break;
1684            }
1685         }
1686       }
1687 
1688       TRACE_SYMTAB(" [sec %2ld]  %s %s  al%2u  foff %6ld .. %6ld  "
1689                   "  svma %p  name \"%s\"\n",
1690                   i, inrx ? "rx" : "  ", inrw ? "rw" : "  ", alyn,
1691                   foff, foff+size-1, (void*)svma, name );
1692 
1693       /* Check for sane-sized segments.  SHT_NOBITS sections have zero
1694          size in the file. */
1695       if (bits &&
1696           ((foff >= n_oimage) || (foff + (bits ? size : 0) > n_oimage))) {
1697          ML_(symerr)(di, True, "ELF Section extends beyond image end");
1698          goto out;
1699       }
1700 
1701       /* Check for a sane alignment value. */
1702       if (alyn > 0 && -1 == VG_(log2)(alyn)) {
1703          ML_(symerr)(di, True, "ELF Section contains invalid "
1704                                ".sh_addralign value");
1705          goto out;
1706       }
1707 
1708 #     define BAD(_secname)                                 \
1709          do { ML_(symerr)(di, True,                        \
1710                           "Can't make sense of " _secname  \
1711                           " section mapping");             \
1712               /* make sure we don't assert if we find */   \
1713               /* ourselves back in this routine later, */  \
1714               /* with the same di */                       \
1715               di->soname = NULL;                           \
1716               goto out;                                    \
1717          } while (0)
1718 
1719       /* Find avma-s for: .text .data .sdata .rodata .bss .sbss .plt .got .opd
1720          and .eh_frame */
1721 
1722       /* Accept .text where mapped as rx (code), even if zero-sized */
1723       if (0 == VG_(strcmp)(name, ".text")) {
1724          if (inrx && size >= 0 && !di->text_present) {
1725             di->text_present = True;
1726             di->text_svma = svma;
1727             di->text_avma = svma + inrx->bias;
1728             di->text_size = size;
1729             di->text_bias = inrx->bias;
1730             di->text_debug_svma = svma;
1731             di->text_debug_bias = inrx->bias;
1732             TRACE_SYMTAB("acquiring .text svma = %#lx .. %#lx\n",
1733                          di->text_svma,
1734                          di->text_svma + di->text_size - 1);
1735             TRACE_SYMTAB("acquiring .text avma = %#lx .. %#lx\n",
1736                          di->text_avma,
1737                          di->text_avma + di->text_size - 1);
1738             TRACE_SYMTAB("acquiring .text bias = %#lx\n", di->text_bias);
1739          } else {
1740             BAD(".text");
1741          }
1742       }
1743 
1744       /* Accept .data where mapped as rw (data), even if zero-sized */
1745       if (0 == VG_(strcmp)(name, ".data")) {
1746          if (inrw && size >= 0 && !di->data_present) {
1747             di->data_present = True;
1748             di->data_svma = svma;
1749             di->data_avma = svma + inrw->bias;
1750             di->data_size = size;
1751             di->data_bias = inrw->bias;
1752             di->data_debug_svma = svma;
1753             di->data_debug_bias = inrw->bias;
1754             TRACE_SYMTAB("acquiring .data svma = %#lx .. %#lx\n",
1755                          di->data_svma,
1756                          di->data_svma + di->data_size - 1);
1757             TRACE_SYMTAB("acquiring .data avma = %#lx .. %#lx\n",
1758                          di->data_avma,
1759                          di->data_avma + di->data_size - 1);
1760             TRACE_SYMTAB("acquiring .data bias = %#lx\n", di->data_bias);
1761          } else {
1762             BAD(".data");
1763          }
1764       }
1765 
1766       /* Accept .sdata where mapped as rw (data) */
1767       if (0 == VG_(strcmp)(name, ".sdata")) {
1768          if (inrw && size > 0 && !di->sdata_present) {
1769             di->sdata_present = True;
1770             di->sdata_svma = svma;
1771             di->sdata_avma = svma + inrw->bias;
1772             di->sdata_size = size;
1773             di->sdata_bias = inrw->bias;
1774             di->sdata_debug_svma = svma;
1775             di->sdata_debug_bias = inrw->bias;
1776             TRACE_SYMTAB("acquiring .sdata svma = %#lx .. %#lx\n",
1777                          di->sdata_svma,
1778                          di->sdata_svma + di->sdata_size - 1);
1779             TRACE_SYMTAB("acquiring .sdata avma = %#lx .. %#lx\n",
1780                          di->sdata_avma,
1781                          di->sdata_avma + di->sdata_size - 1);
1782             TRACE_SYMTAB("acquiring .sdata bias = %#lx\n", di->sdata_bias);
1783          } else {
1784             BAD(".sdata");
1785          }
1786       }
1787 
1788       /* Accept .rodata where mapped as rx (data), even if zero-sized */
1789       if (0 == VG_(strcmp)(name, ".rodata")) {
1790          if (inrx && size >= 0 && !di->rodata_present) {
1791             di->rodata_present = True;
1792             di->rodata_svma = svma;
1793             di->rodata_avma = svma + inrx->bias;
1794             di->rodata_size = size;
1795             di->rodata_bias = inrx->bias;
1796             di->rodata_debug_svma = svma;
1797             di->rodata_debug_bias = inrx->bias;
1798                                     /* NB was 'inrw' prior to r11794 */
1799             TRACE_SYMTAB("acquiring .rodata svma = %#lx .. %#lx\n",
1800                          di->rodata_svma,
1801                          di->rodata_svma + di->rodata_size - 1);
1802             TRACE_SYMTAB("acquiring .rodata avma = %#lx .. %#lx\n",
1803                          di->rodata_avma,
1804                          di->rodata_avma + di->rodata_size - 1);
1805             TRACE_SYMTAB("acquiring .rodata bias = %#lx\n", di->rodata_bias);
1806          } else {
1807             BAD(".rodata");
1808          }
1809       }
1810 
1811       if (0 == VG_(strcmp)(name, ".dynbss")) {
1812          if (inrw && size > 0 && !di->bss_present) {
1813             dynbss_present = True;
1814             di->bss_present = True;
1815             di->bss_svma = svma;
1816             di->bss_avma = svma + inrw->bias;
1817             di->bss_size = size;
1818             di->bss_bias = inrw->bias;
1819             di->bss_debug_svma = svma;
1820             di->bss_debug_bias = inrw->bias;
1821             TRACE_SYMTAB("acquiring .dynbss svma = %#lx .. %#lx\n",
1822                          di->bss_svma,
1823                          di->bss_svma + di->bss_size - 1);
1824             TRACE_SYMTAB("acquiring .dynbss avma = %#lx .. %#lx\n",
1825                          di->bss_avma,
1826                          di->bss_avma + di->bss_size - 1);
1827             TRACE_SYMTAB("acquiring .dynbss bias = %#lx\n", di->bss_bias);
1828          }
1829       }
1830 
1831       /* Accept .bss where mapped as rw (data), even if zero-sized */
1832       if (0 == VG_(strcmp)(name, ".bss")) {
1833          if (inrw && size > 0 && dynbss_present) {
1834             vg_assert(di->bss_present);
1835             dynbss_present = False;
1836             vg_assert(di->bss_svma + di->bss_size == svma);
1837             di->bss_size += size;
1838             TRACE_SYMTAB("acquiring .bss svma = %#lx .. %#lx\n",
1839                          svma, svma + size - 1);
1840             TRACE_SYMTAB("acquiring .bss avma = %#lx .. %#lx\n",
1841                          svma + inrw->bias, svma + inrw->bias + size - 1);
1842             TRACE_SYMTAB("acquiring .bss bias = %#lx\n", di->bss_bias);
1843          } else
1844 
1845          if (inrw && size >= 0 && !di->bss_present) {
1846             di->bss_present = True;
1847             di->bss_svma = svma;
1848             di->bss_avma = svma + inrw->bias;
1849             di->bss_size = size;
1850             di->bss_bias = inrw->bias;
1851             di->bss_debug_svma = svma;
1852             di->bss_debug_bias = inrw->bias;
1853             TRACE_SYMTAB("acquiring .bss svma = %#lx .. %#lx\n",
1854                          di->bss_svma,
1855                          di->bss_svma + di->bss_size - 1);
1856             TRACE_SYMTAB("acquiring .bss avma = %#lx .. %#lx\n",
1857                          di->bss_avma,
1858                          di->bss_avma + di->bss_size - 1);
1859             TRACE_SYMTAB("acquiring .bss bias = %#lx\n", di->bss_bias);
1860          } else
1861 
1862          /* Now one from the wtf?! department ... */
1863          if (inrx && (!inrw) && size >= 0 && !di->bss_present) {
1864             /* File contains a .bss, but it got mapped as rx only.
1865                This is very strange.  For now, just pretend we didn't
1866                see it :-) */
1867             di->bss_present = False;
1868             di->bss_svma = 0;
1869             di->bss_avma = 0;
1870             di->bss_size = 0;
1871             di->bss_bias = 0;
1872             di->bss_debug_svma = 0;
1873             di->bss_debug_bias = 0;
1874             if (!VG_(clo_xml)) {
1875                VG_(message)(Vg_UserMsg,
1876                             "Warning: the following file's .bss is "
1877                             "mapped r-x only - ignoring .bss syms\n");
1878                VG_(message)(Vg_UserMsg,   " %s\n", di->fsm.filename
1879                                                       ? di->fsm.filename
1880                                                       : (UChar*)"(null?!)" );
1881             }
1882          } else
1883 
1884          if ((!inrw) && (!inrx) && size >= 0 && !di->bss_present) {
1885             /* File contains a .bss, but it didn't get mapped.  Ignore. */
1886             di->bss_present = False;
1887             di->bss_svma = 0;
1888             di->bss_avma = 0;
1889             di->bss_size = 0;
1890             di->bss_bias = 0;
1891          } else {
1892             BAD(".bss");
1893          }
1894       }
1895 
1896       if (0 == VG_(strcmp)(name, ".sdynbss")) {
1897          if (inrw && size >= 0 && !di->sbss_present) {
1898             sdynbss_present = True;
1899             di->sbss_present = True;
1900             di->sbss_svma = svma;
1901             di->sbss_avma = svma + inrw->bias;
1902             di->sbss_size = size;
1903             di->sbss_bias = inrw->bias;
1904             di->sbss_debug_svma = svma;
1905             di->sbss_debug_bias = inrw->bias;
1906             TRACE_SYMTAB("acquiring .sdynbss svma = %#lx .. %#lx\n",
1907                          di->sbss_svma,
1908                          di->sbss_svma + di->sbss_size - 1);
1909             TRACE_SYMTAB("acquiring .sdynbss avma = %#lx .. %#lx\n",
1910                          di->sbss_avma,
1911                          di->sbss_avma + di->sbss_size - 1);
1912             TRACE_SYMTAB("acquiring .sdynbss bias = %#lx\n", di->sbss_bias);
1913          }
1914       }
1915 
1916       /* Accept .sbss where mapped as rw (data) */
1917       if (0 == VG_(strcmp)(name, ".sbss")) {
1918          if (inrw && size > 0 && sdynbss_present) {
1919             vg_assert(di->sbss_present);
1920             sdynbss_present = False;
1921             vg_assert(di->sbss_svma + di->sbss_size == svma);
1922             di->sbss_size += size;
1923             TRACE_SYMTAB("acquiring .sbss svma = %#lx .. %#lx\n",
1924                          svma, svma + size - 1);
1925             TRACE_SYMTAB("acquiring .sbss avma = %#lx .. %#lx\n",
1926                          svma + inrw->bias, svma + inrw->bias + size - 1);
1927             TRACE_SYMTAB("acquiring .sbss bias = %#lx\n", di->sbss_bias);
1928          } else
1929 
1930          if (inrw && size > 0 && !di->sbss_present) {
1931             di->sbss_present = True;
1932             di->sbss_svma = svma;
1933             di->sbss_avma = svma + inrw->bias;
1934             di->sbss_size = size;
1935             di->sbss_bias = inrw->bias;
1936             di->sbss_debug_svma = svma;
1937             di->sbss_debug_bias = inrw->bias;
1938             TRACE_SYMTAB("acquiring .sbss svma = %#lx .. %#lx\n",
1939                          di->sbss_svma,
1940                          di->sbss_svma + di->sbss_size - 1);
1941             TRACE_SYMTAB("acquiring .sbss avma = %#lx .. %#lx\n",
1942                          di->sbss_avma,
1943                          di->sbss_avma + di->sbss_size - 1);
1944             TRACE_SYMTAB("acquiring .sbss bias = %#lx\n", di->sbss_bias);
1945          } else {
1946             BAD(".sbss");
1947          }
1948       }
1949 
1950       /* Accept .got where mapped as rw (data) */
1951       if (0 == VG_(strcmp)(name, ".got")) {
1952          if (inrw && size > 0 && !di->got_present) {
1953             di->got_present = True;
1954             di->got_avma = svma + inrw->bias;
1955             di->got_size = size;
1956             TRACE_SYMTAB("acquiring .got avma = %#lx\n", di->got_avma);
1957          } else {
1958             BAD(".got");
1959          }
1960       }
1961 
1962       /* Accept .got.plt where mapped as rw (data) */
1963       if (0 == VG_(strcmp)(name, ".got.plt")) {
1964          if (inrw && size > 0 && !di->gotplt_present) {
1965             di->gotplt_present = True;
1966             di->gotplt_avma = svma + inrw->bias;
1967             di->gotplt_size = size;
1968             TRACE_SYMTAB("acquiring .got.plt avma = %#lx\n", di->gotplt_avma);
1969          } else if (size != 0) {
1970             BAD(".got.plt");
1971          }
1972       }
1973 
1974       /* PLT is different on different platforms, it seems. */
1975 #     if defined(VGP_x86_linux) || defined(VGP_amd64_linux) \
1976          || defined(VGP_arm_linux) || defined (VGP_s390x_linux)
1977       /* Accept .plt where mapped as rx (code) */
1978       if (0 == VG_(strcmp)(name, ".plt")) {
1979          if (inrx && size > 0 && !di->plt_present) {
1980             di->plt_present = True;
1981             di->plt_avma = svma + inrx->bias;
1982             di->plt_size = size;
1983             TRACE_SYMTAB("acquiring .plt avma = %#lx\n", di->plt_avma);
1984          } else {
1985             BAD(".plt");
1986          }
1987       }
1988 #     elif defined(VGP_ppc32_linux)
1989       /* Accept .plt where mapped as rw (data) */
1990       if (0 == VG_(strcmp)(name, ".plt")) {
1991          if (inrw && size > 0 && !di->plt_present) {
1992             di->plt_present = True;
1993             di->plt_avma = svma + inrw->bias;
1994             di->plt_size = size;
1995             TRACE_SYMTAB("acquiring .plt avma = %#lx\n", di->plt_avma);
1996          } else {
1997             BAD(".plt");
1998          }
1999       }
2000 #     elif defined(VGP_ppc64_linux)
2001       /* Accept .plt where mapped as rw (data), or unmapped */
2002       if (0 == VG_(strcmp)(name, ".plt")) {
2003          if (inrw && size > 0 && !di->plt_present) {
2004             di->plt_present = True;
2005             di->plt_avma = svma + inrw->bias;
2006             di->plt_size = size;
2007             TRACE_SYMTAB("acquiring .plt avma = %#lx\n", di->plt_avma);
2008          } else
2009          if ((!inrw) && (!inrx) && size > 0 && !di->plt_present) {
2010             /* File contains a .plt, but it didn't get mapped.
2011                Presumably it is not required on this platform.  At
2012                least don't reject the situation as invalid. */
2013             di->plt_present = True;
2014             di->plt_avma = 0;
2015             di->plt_size = 0;
2016          } else {
2017             BAD(".plt");
2018          }
2019       }
2020 #     else
2021 #       error "Unsupported platform"
2022 #     endif
2023 
2024       /* Accept .opd where mapped as rw (data) */
2025       if (0 == VG_(strcmp)(name, ".opd")) {
2026          if (inrw && size > 0 && !di->opd_present) {
2027             di->opd_present = True;
2028             di->opd_avma = svma + inrw->bias;
2029             di->opd_size = size;
2030             TRACE_SYMTAB("acquiring .opd avma = %#lx\n", di->opd_avma);
2031          } else {
2032             BAD(".opd");
2033          }
2034       }
2035 
2036       /* Accept .eh_frame where mapped as rx (code).  This seems to be
2037          the common case.  However, if that doesn't pan out, try for
2038          rw (data) instead.  We can handle up to N_EHFRAME_SECTS per
2039          ELF object. */
2040       if (0 == VG_(strcmp)(name, ".eh_frame")) {
2041          if (inrx && size > 0 && di->n_ehframe < N_EHFRAME_SECTS) {
2042             di->ehframe_avma[di->n_ehframe] = svma + inrx->bias;
2043             di->ehframe_size[di->n_ehframe] = size;
2044             TRACE_SYMTAB("acquiring .eh_frame avma = %#lx\n",
2045                          di->ehframe_avma[di->n_ehframe]);
2046             di->n_ehframe++;
2047          } else
2048          if (inrw && size > 0 && di->n_ehframe < N_EHFRAME_SECTS) {
2049             di->ehframe_avma[di->n_ehframe] = svma + inrw->bias;
2050             di->ehframe_size[di->n_ehframe] = size;
2051             TRACE_SYMTAB("acquiring .eh_frame avma = %#lx\n",
2052                          di->ehframe_avma[di->n_ehframe]);
2053             di->n_ehframe++;
2054          } else {
2055             BAD(".eh_frame");
2056          }
2057       }
2058 
2059 #    undef BAD
2060 
2061    } /* iterate over the section headers */
2062 
2063    /* TOPLEVEL */
2064    if (0) VG_(printf)("YYYY text_: avma %#lx  size %ld  bias %#lx\n",
2065                       di->text_avma, di->text_size, di->text_bias);
2066 
2067    if (VG_(clo_verbosity) > 2 || VG_(clo_trace_redir))
2068       VG_(message)(Vg_DebugMsg, "   svma %#010lx, avma %#010lx\n",
2069                                 di->text_avma - di->text_bias,
2070                                 di->text_avma );
2071 
2072    TRACE_SYMTAB("\n");
2073    TRACE_SYMTAB("------ Finding image addresses "
2074                 "for debug-info sections ------\n");
2075 
2076    /* TOPLEVEL */
2077    /* Find interesting sections, read the symbol table(s), read any debug
2078       information */
2079    {
2080       /* IMAGE addresses: pointers to start of sections in the
2081          transiently loaded oimage, not in the fragments of the file
2082          mapped in by the guest's dynamic linker. */
2083       /* TOPLEVEL */
2084       UChar*     strtab_img       = NULL; /* .strtab */
2085       ElfXX_Sym* symtab_img       = NULL; /* .symtab */
2086       UChar*     dynstr_img       = NULL; /* .dynstr */
2087       ElfXX_Sym* dynsym_img       = NULL; /* .dynsym */
2088       UChar*     debuglink_img    = NULL; /* .gnu_debuglink */
2089       UChar*     stab_img         = NULL; /* .stab         (stabs)  */
2090       UChar*     stabstr_img      = NULL; /* .stabstr      (stabs)  */
2091       UChar*     debug_line_img   = NULL; /* .debug_line   (dwarf2) */
2092       UChar*     debug_info_img   = NULL; /* .debug_info   (dwarf2) */
2093       UChar*     debug_abbv_img   = NULL; /* .debug_abbrev (dwarf2) */
2094       UChar*     debug_str_img    = NULL; /* .debug_str    (dwarf2) */
2095       UChar*     debug_ranges_img = NULL; /* .debug_ranges (dwarf2) */
2096       UChar*     debug_loc_img    = NULL; /* .debug_loc    (dwarf2) */
2097       UChar*     debug_frame_img  = NULL; /* .debug_frame  (dwarf2) */
2098       UChar*     dwarf1d_img      = NULL; /* .debug        (dwarf1) */
2099       UChar*     dwarf1l_img      = NULL; /* .line         (dwarf1) */
2100       UChar*     opd_img          = NULL; /* .opd (dwarf2,
2101                                                    ppc64-linux) */
2102       UChar*     ehframe_img[N_EHFRAME_SECTS]; /* .eh_frame (dwarf2) */
2103 
2104       /* Section sizes, in bytes */
2105       SizeT      strtab_sz       = 0;
2106       SizeT      symtab_sz       = 0;
2107       SizeT      dynstr_sz       = 0;
2108       SizeT      dynsym_sz       = 0;
2109       SizeT      debuglink_sz    = 0;
2110       SizeT      stab_sz         = 0;
2111       SizeT      stabstr_sz      = 0;
2112       SizeT      debug_line_sz   = 0;
2113       SizeT      debug_info_sz   = 0;
2114       SizeT      debug_abbv_sz   = 0;
2115       SizeT      debug_str_sz    = 0;
2116       SizeT      debug_ranges_sz = 0;
2117       SizeT      debug_loc_sz    = 0;
2118       SizeT      debug_frame_sz  = 0;
2119       SizeT      dwarf1d_sz      = 0;
2120       SizeT      dwarf1l_sz      = 0;
2121       SizeT      opd_sz_unused   = 0;
2122       SizeT      ehframe_sz[N_EHFRAME_SECTS];
2123 
2124       for (i = 0; i < N_EHFRAME_SECTS; i++) {
2125          ehframe_img[i] = NULL;
2126          ehframe_sz[i]  = 0;
2127       }
2128 
2129       /* Find all interesting sections */
2130 
2131       UInt ehframe_ix = 0;
2132 
2133       /* What FIND does: it finds the section called _SEC_NAME.  The
2134          size of it is assigned to _SEC_SIZE.  The address of the
2135          section in the transiently loaded oimage is assigned to
2136          _SEC_IMG.  If the section is found, _POST_FX is executed
2137          after _SEC_NAME and _SEC_SIZE have been assigned to.
2138 
2139          Even for sections which are marked loadable, the client's
2140          ld.so may not have loaded them yet, so there is no guarantee
2141          that we can safely prod around in any such area).  Because
2142          the entire object file is transiently mapped aboard for
2143          inspection, it's always safe to inspect that area. */
2144 
2145       /* TOPLEVEL */
2146       /* Iterate over section headers (again) */
2147       for (i = 0; i < ehdr_img->e_shnum; i++) {
2148 
2149 #        define FINDX(_sec_name, _sec_size, _sec_img, _post_fx)     \
2150          do { ElfXX_Shdr* shdr \
2151                  = INDEX_BIS( shdr_img, i, shdr_ent_szB ); \
2152             if (0 == VG_(strcmp)(_sec_name, shdr_strtab_img \
2153                                             + shdr->sh_name)) { \
2154                Bool nobits; \
2155                _sec_img  = (void*)(oimage + shdr->sh_offset); \
2156                _sec_size = shdr->sh_size; \
2157                nobits    = shdr->sh_type == SHT_NOBITS; \
2158                TRACE_SYMTAB( "%18s:  img %p .. %p\n", \
2159                              _sec_name, (UChar*)_sec_img, \
2160                              ((UChar*)_sec_img) + _sec_size - 1); \
2161                /* SHT_NOBITS sections have zero size in the file. */ \
2162                if ( shdr->sh_offset \
2163                     + (nobits ? 0 : _sec_size) > n_oimage ) { \
2164                   ML_(symerr)(di, True, \
2165                               "   section beyond image end?!"); \
2166                   goto out; \
2167                } \
2168                _post_fx; \
2169             } \
2170          } while (0);
2171 
2172          /* Version with no post-effects */
2173 #        define FIND(_sec_name, _sec_size, _sec_img) \
2174             FINDX(_sec_name, _sec_size, _sec_img, /**/)
2175 
2176          /*   NAME              SIZE             IMAGE addr */
2177          FIND(".dynsym",        dynsym_sz,       dynsym_img)
2178          FIND(".dynstr",        dynstr_sz,       dynstr_img)
2179          FIND(".symtab",        symtab_sz,       symtab_img)
2180          FIND(".strtab",        strtab_sz,       strtab_img)
2181 
2182          FIND(".gnu_debuglink", debuglink_sz,    debuglink_img)
2183 
2184          FIND(".stab",          stab_sz,         stab_img)
2185          FIND(".stabstr",       stabstr_sz,      stabstr_img)
2186 
2187          FIND(".debug_line",    debug_line_sz,   debug_line_img)
2188          FIND(".debug_info",    debug_info_sz,   debug_info_img)
2189          FIND(".debug_abbrev",  debug_abbv_sz,   debug_abbv_img)
2190          FIND(".debug_str",     debug_str_sz,    debug_str_img)
2191          FIND(".debug_ranges",  debug_ranges_sz, debug_ranges_img)
2192          FIND(".debug_loc",     debug_loc_sz,    debug_loc_img)
2193          FIND(".debug_frame",   debug_frame_sz,  debug_frame_img)
2194 
2195          FIND(".debug",         dwarf1d_sz,      dwarf1d_img)
2196          FIND(".line",          dwarf1l_sz,      dwarf1l_img)
2197 
2198          FIND(".opd",           opd_sz_unused,   opd_img)
2199 
2200          FINDX(".eh_frame",     ehframe_sz[ehframe_ix],
2201                                                  ehframe_img[ehframe_ix],
2202                do { ehframe_ix++; vg_assert(ehframe_ix <= N_EHFRAME_SECTS); }
2203                     while (0)
2204          )
2205          /* Comment_on_EH_FRAME_MULTIPLE_INSTANCES: w.r.t. .eh_frame
2206             multi-instance kludgery, how are we assured that the order
2207             in which we fill in ehframe_sz[] and ehframe_img[] is
2208             consistent with the order in which we previously filled in
2209             di->ehframe_avma[] and di->ehframe_size[] ?  By the fact
2210             that in both cases, these arrays were filled in by
2211             iterating over the section headers top-to-bottom.  So both
2212             loops (this one and the previous one) encounter the
2213             .eh_frame entries in the same order and so fill in these
2214             arrays in a consistent order.
2215          */
2216 
2217 #        undef FINDX
2218 #        undef FIND
2219       } /* Iterate over section headers (again) */
2220 
2221       /* TOPLEVEL */
2222       /* Now, see if we can find a debuginfo object, and if so map it in, and
2223          put the mapping address and size in dimage and n_dimage. */
2224       vg_assert(dimage == 0 && n_dimage == 0);
2225 
2226       /* Look for a build-id */
2227       buildid = find_buildid(oimage, n_oimage);
2228 
2229       /* Look for a debug image */
2230       if (buildid != NULL || debuglink_img != NULL) {
2231          /* Do have a debuglink section? */
2232          if (debuglink_img != NULL) {
2233             UInt crc_offset = VG_ROUNDUP(VG_(strlen)(debuglink_img)+1, 4);
2234             UInt crc;
2235 
2236             vg_assert(crc_offset + sizeof(UInt) <= debuglink_sz);
2237 
2238             /* Extract the CRC from the debuglink section */
2239             crc = ML_(read_UInt)(debuglink_img + crc_offset);
2240 
2241             /* See if we can find a matching debug file */
2242             find_debug_file( di, di->fsm.filename, buildid,
2243                              debuglink_img, crc, &dimage, &n_dimage );
2244          } else {
2245             /* See if we can find a matching debug file */
2246             find_debug_file( di, di->fsm.filename, buildid,
2247                              NULL, 0, &dimage, &n_dimage );
2248          }
2249       }
2250 
2251       if (buildid) {
2252          ML_(dinfo_free)(buildid);
2253          buildid = NULL; /* paranoia */
2254       }
2255 
2256       /* Still no luck?  Let's have one last roll of the dice. */
2257       if (dimage == 0) {
2258          vg_assert(n_dimage == 0);
2259          Bool found = find_ad_hoc_debug_image( di, di->fsm.filename,
2260                                                &dimage, &n_dimage );
2261          if (found)
2262             vg_assert(dimage != 0);
2263       }
2264 
2265       /* TOPLEVEL */
2266       /* If we were successful in finding a debug image, pull various
2267          SVMA/bias/size and image addresses out of it. */
2268       if (dimage != 0
2269           && n_dimage >= sizeof(ElfXX_Ehdr)
2270           && ML_(is_elf_object_file)((void*)dimage, n_dimage)) {
2271 
2272          /* Pull out and validate program header and section header info */
2273          ElfXX_Ehdr* ehdr_dimg     = (ElfXX_Ehdr*)dimage;
2274          ElfXX_Phdr* phdr_dimg     = (ElfXX_Phdr*)( ((UChar*)ehdr_dimg)
2275                                                        + ehdr_dimg->e_phoff );
2276          UWord       phdr_dnent    = ehdr_dimg->e_phnum;
2277          UWord       phdr_dent_szB = ehdr_dimg->e_phentsize;
2278          ElfXX_Shdr* shdr_dimg     = (ElfXX_Shdr*)( ((UChar*)ehdr_dimg)
2279                                                        + ehdr_dimg->e_shoff );
2280          UWord       shdr_dnent       = ehdr_dimg->e_shnum;
2281          UWord       shdr_dent_szB    = ehdr_dimg->e_shentsize;
2282          UChar*      shdr_strtab_dimg = NULL;
2283 
2284          /* SVMAs covered by rx and rw segments and corresponding bias. */
2285          /* Addr     rx_dsvma_base = 0; */ /* UNUSED */
2286          Addr     rx_dsvma_limit = 0;
2287          PtrdiffT rx_dbias = 0;
2288          /* Addr     rw_dsvma_base = 0; */ /* UNUSED */
2289          Addr     rw_dsvma_limit = 0;
2290          PtrdiffT rw_dbias = 0;
2291 
2292          Bool need_symtab, need_stabs, need_dwarf2, need_dwarf1;
2293 
2294          if (phdr_dnent == 0
2295              || !contained_within(
2296                     dimage, n_dimage,
2297                     (Addr)phdr_dimg, phdr_dnent * phdr_dent_szB)) {
2298             ML_(symerr)(di, True,
2299                         "Missing or invalid ELF Program Header Table"
2300                         " (debuginfo file)");
2301             goto out;
2302          }
2303 
2304          if (shdr_dnent == 0
2305              || !contained_within(
2306                     dimage, n_dimage,
2307                     (Addr)shdr_dimg, shdr_dnent * shdr_dent_szB)) {
2308             ML_(symerr)(di, True,
2309                         "Missing or invalid ELF Section Header Table"
2310                         " (debuginfo file)");
2311             goto out;
2312          }
2313 
2314          /* Also find the section header's string table, and validate. */
2315          /* checked previously by is_elf_object_file: */
2316          vg_assert( ehdr_dimg->e_shstrndx != SHN_UNDEF );
2317 
2318          shdr_strtab_dimg
2319             = (UChar*)( ((UChar*)ehdr_dimg)
2320                         + shdr_dimg[ehdr_dimg->e_shstrndx].sh_offset);
2321          if (!contained_within(
2322                  dimage, n_dimage,
2323                  (Addr)shdr_strtab_dimg,
2324                  1/*bogus, but we don't know the real size*/ )) {
2325             ML_(symerr)(di, True,
2326                         "Invalid ELF Section Header String Table"
2327                         " (debuginfo file)");
2328             goto out;
2329          }
2330 
2331          need_symtab = (NULL == symtab_img);
2332          need_stabs  = (NULL == stab_img);
2333          need_dwarf2 = (NULL == debug_info_img);
2334          need_dwarf1 = (NULL == dwarf1d_img);
2335 
2336          for (i = 0; i < ehdr_dimg->e_phnum; i++) {
2337             ElfXX_Phdr* phdr
2338                = INDEX_BIS( (void*)(dimage + ehdr_dimg->e_phoff),
2339                                        i, phdr_ent_szB );
2340             if (phdr->p_type == PT_LOAD) {
2341                if (rx_dsvma_limit == 0
2342                    && phdr->p_offset >= di->fsm.rx_map_foff
2343                    && phdr->p_offset
2344                       < di->fsm.rx_map_foff + di->fsm.rx_map_size
2345                    && phdr->p_offset + phdr->p_filesz
2346                       <= di->fsm.rx_map_foff + di->fsm.rx_map_size) {
2347                   /* rx_dsvma_base = phdr->p_vaddr; */ /* UNUSED */
2348                   rx_dsvma_limit = phdr->p_vaddr + phdr->p_memsz;
2349                   rx_dbias = di->fsm.rx_map_avma - di->fsm.rx_map_foff
2350                              + phdr->p_offset - phdr->p_vaddr;
2351                }
2352                else
2353                if (rw_dsvma_limit == 0
2354                    && phdr->p_offset >= di->fsm.rw_map_foff
2355                    && phdr->p_offset
2356                       < di->fsm.rw_map_foff + di->fsm.rw_map_size
2357                    && phdr->p_offset + phdr->p_filesz
2358                       <= di->fsm.rw_map_foff + di->fsm.rw_map_size) {
2359                   /* rw_dsvma_base = phdr->p_vaddr; */ /* UNUSED */
2360                   rw_dsvma_limit = phdr->p_vaddr + phdr->p_memsz;
2361                   rw_dbias = di->fsm.rw_map_avma - di->fsm.rw_map_foff
2362                              + phdr->p_offset - phdr->p_vaddr;
2363                }
2364             }
2365          }
2366 
2367          /* Find all interesting sections */
2368          for (i = 0; i < ehdr_dimg->e_shnum; i++) {
2369 
2370             /* Find debug svma and bias information for sections
2371                we found in the main file. */
2372 
2373 #           define FIND(sec, seg) \
2374             do { ElfXX_Shdr* shdr \
2375                     = INDEX_BIS( shdr_dimg, i, shdr_dent_szB ); \
2376                if (di->sec##_present \
2377                    && 0 == VG_(strcmp)("." #sec, \
2378                                        shdr_strtab_dimg + shdr->sh_name)) { \
2379                   vg_assert(di->sec##_size == shdr->sh_size); \
2380                   vg_assert(di->sec##_avma +  shdr->sh_addr + seg##_dbias); \
2381                   /* Assume we have a correct value for the main */ \
2382                   /* object's bias.  Use that to derive the debuginfo */ \
2383                   /* object's bias, by adding the difference in SVMAs */ \
2384                   /* for the corresponding sections in the two files. */ \
2385                   /* That should take care of all prelinking effects. */ \
2386                   di->sec##_debug_svma = shdr->sh_addr; \
2387                   di->sec##_debug_bias \
2388                      = di->sec##_bias + \
2389                        di->sec##_svma - di->sec##_debug_svma; \
2390                   TRACE_SYMTAB("acquiring ." #sec \
2391                                " debug svma = %#lx .. %#lx\n",       \
2392                                di->sec##_debug_svma, \
2393                                di->sec##_debug_svma + di->sec##_size - 1); \
2394                   TRACE_SYMTAB("acquiring ." #sec " debug bias = %#lx\n", \
2395                                di->sec##_debug_bias); \
2396                } \
2397             } while (0);
2398 
2399             /* SECTION   SEGMENT */
2400             FIND(text,   rx)
2401             FIND(data,   rw)
2402             FIND(sdata,  rw)
2403             FIND(rodata, rw)
2404             FIND(bss,    rw)
2405             FIND(sbss,   rw)
2406 
2407 #           undef FIND
2408 
2409             /* Same deal as previous FIND, except only do it for those
2410                sections for which we didn't find anything useful in
2411                the main file. */
2412 
2413 #           define FIND(condition, sec_name, sec_size, sec_img) \
2414             do { ElfXX_Shdr* shdr \
2415                     = INDEX_BIS( shdr_dimg, i, shdr_dent_szB ); \
2416                if (condition \
2417                    && 0 == VG_(strcmp)(sec_name, \
2418                                        shdr_strtab_dimg + shdr->sh_name)) { \
2419                   Bool nobits; \
2420                   if (0 != sec_img) \
2421                      VG_(core_panic)("repeated section!\n"); \
2422                   sec_img  = (void*)(dimage + shdr->sh_offset); \
2423                   sec_size = shdr->sh_size; \
2424                   nobits   = shdr->sh_type == SHT_NOBITS; \
2425                   TRACE_SYMTAB( "%18s: dimg %p .. %p\n", \
2426                                 sec_name, \
2427                                 (UChar*)sec_img, \
2428                                 ((UChar*)sec_img) + sec_size - 1); \
2429                   /* SHT_NOBITS sections have zero size in the file. */ \
2430                   if ( shdr->sh_offset \
2431                        + (nobits ? 0 : sec_size) > n_dimage ) { \
2432                      ML_(symerr)(di, True, \
2433                                  "   section beyond image end?!"); \
2434                      goto out; \
2435                   } \
2436                } \
2437             } while (0);
2438 
2439             /* NEEDED?        NAME             SIZE           IMAGE addr */
2440             FIND(need_symtab, ".symtab",       symtab_sz,     symtab_img)
2441             FIND(need_symtab, ".strtab",       strtab_sz,     strtab_img)
2442             FIND(need_stabs,  ".stab",         stab_sz,       stab_img)
2443             FIND(need_stabs,  ".stabstr",      stabstr_sz,    stabstr_img)
2444             FIND(need_dwarf2, ".debug_line",   debug_line_sz, debug_line_img)
2445             FIND(need_dwarf2, ".debug_info",   debug_info_sz, debug_info_img)
2446             FIND(need_dwarf2, ".debug_abbrev", debug_abbv_sz, debug_abbv_img)
2447             FIND(need_dwarf2, ".debug_str",    debug_str_sz,  debug_str_img)
2448             FIND(need_dwarf2, ".debug_ranges", debug_ranges_sz,
2449                                                             debug_ranges_img)
2450             FIND(need_dwarf2, ".debug_loc",    debug_loc_sz,  debug_loc_img)
2451             FIND(need_dwarf2, ".debug_frame",  debug_frame_sz,
2452                                                             debug_frame_img)
2453             FIND(need_dwarf1, ".debug",        dwarf1d_sz,    dwarf1d_img)
2454             FIND(need_dwarf1, ".line",         dwarf1l_sz,    dwarf1l_img)
2455 
2456 #           undef FIND
2457          } /* Find all interesting sections */
2458       } /* do we have a debug image? */
2459 
2460       /* TOPLEVEL */
2461       /* Check some sizes */
2462       vg_assert((dynsym_sz % sizeof(ElfXX_Sym)) == 0);
2463       vg_assert((symtab_sz % sizeof(ElfXX_Sym)) == 0);
2464 
2465       /* Read symbols */
2466       {
2467          void (*read_elf_symtab)(struct _DebugInfo*,UChar*,
2468                                  ElfXX_Sym*,SizeT,
2469                                  UChar*,SizeT,
2470                                  Bool,UChar*);
2471          Bool symtab_in_debug;
2472 #        if defined(VGP_ppc64_linux)
2473          read_elf_symtab = read_elf_symtab__ppc64_linux;
2474 #        else
2475          read_elf_symtab = read_elf_symtab__normal;
2476 #        endif
2477          symtab_in_debug = (Addr)symtab_img >= dimage
2478                            && (Addr)symtab_img < dimage + n_dimage;
2479          read_elf_symtab(di, "symbol table",
2480                          symtab_img, symtab_sz,
2481                          strtab_img, strtab_sz,
2482                          symtab_in_debug, opd_img);
2483 
2484          read_elf_symtab(di, "dynamic symbol table",
2485                          dynsym_img, dynsym_sz,
2486                          dynstr_img, dynstr_sz,
2487                          False, opd_img);
2488       } /* Read symbols */
2489 
2490       /* TOPLEVEL */
2491       /* Read .eh_frame and .debug_frame (call-frame-info) if any.  Do
2492          the .eh_frame section(s) first. */
2493       vg_assert(di->n_ehframe >= 0 && di->n_ehframe <= N_EHFRAME_SECTS);
2494       for (i = 0; i < di->n_ehframe; i++) {
2495          /* see Comment_on_EH_FRAME_MULTIPLE_INSTANCES above for why
2496             this next assertion should hold. */
2497          vg_assert(ehframe_sz[i] == di->ehframe_size[i]);
2498          ML_(read_callframe_info_dwarf3)( di,
2499                                           ehframe_img[i],
2500                                           ehframe_sz[i],
2501                                           di->ehframe_avma[i],
2502                                           True/*is_ehframe*/ );
2503       }
2504       if (debug_frame_sz) {
2505          ML_(read_callframe_info_dwarf3)( di,
2506                                           debug_frame_img, debug_frame_sz,
2507                                           0/*assume zero avma*/,
2508                                           False/*!is_ehframe*/ );
2509       }
2510 
2511       /* Read the stabs and/or dwarf2 debug information, if any.  It
2512          appears reading stabs stuff on amd64-linux doesn't work, so
2513          we ignore it.  On s390x stabs also doesnt work and we always
2514          have the dwarf info in the eh_frame.  We also segfault on
2515          ppc64-linux when reading stabs, so skip that.  ppc32-linux
2516          seems OK though.  Also skip on Android. */
2517 #     if !defined(VGP_amd64_linux) \
2518          && !defined(VGP_s390x_linux) \
2519          && !defined(VGP_ppc64_linux) \
2520          && !defined(VGPV_arm_linux_android) \
2521          && !defined(VGPV_x86_linux_android)
2522       if (stab_img && stabstr_img) {
2523          ML_(read_debuginfo_stabs) ( di, stab_img, stab_sz,
2524                                          stabstr_img, stabstr_sz );
2525       }
2526 #     endif
2527       /* jrs 2006-01-01: icc-8.1 has been observed to generate
2528          binaries without debug_str sections.  Don't preclude
2529          debuginfo reading for that reason, but, in
2530          read_unitinfo_dwarf2, do check that debugstr is non-NULL
2531          before using it. */
2532       if (debug_info_img && debug_abbv_img && debug_line_img
2533                                            /* && debug_str_img */) {
2534 
2535          /* The old reader: line numbers and unwind info only */
2536          ML_(read_debuginfo_dwarf3) ( di,
2537                                       debug_info_img, debug_info_sz,
2538                                       debug_abbv_img, debug_abbv_sz,
2539                                       debug_line_img, debug_line_sz,
2540                                       debug_str_img,  debug_str_sz );
2541 
2542          /* The new reader: read the DIEs in .debug_info to acquire
2543             information on variable types and locations.  But only if
2544             the tool asks for it, or the user requests it on the
2545             command line. */
2546          if (VG_(needs).var_info /* the tool requires it */
2547              || VG_(clo_read_var_info) /* the user asked for it */) {
2548             ML_(new_dwarf3_reader)(
2549                di, debug_info_img,   debug_info_sz,
2550                    debug_abbv_img,   debug_abbv_sz,
2551                    debug_line_img,   debug_line_sz,
2552                    debug_str_img,    debug_str_sz,
2553                    debug_ranges_img, debug_ranges_sz,
2554                    debug_loc_img,    debug_loc_sz
2555             );
2556          }
2557       }
2558       if (dwarf1d_img && dwarf1l_img) {
2559          ML_(read_debuginfo_dwarf1) ( di, dwarf1d_img, dwarf1d_sz,
2560                                           dwarf1l_img, dwarf1l_sz );
2561       }
2562       /* TOPLEVEL */
2563 
2564    } /* "Find interesting sections, read the symbol table(s), read any debug
2565         information" (a local scope) */
2566 
2567    /* TOPLEVEL */
2568    res = True;
2569 
2570    /* If reading Dwarf3 variable type/location info, print a line
2571       showing the number of variables read for each object.
2572       (Currently disabled -- is a sanity-check mechanism for
2573       exp-sgcheck.) */
2574    if (0 && (VG_(needs).var_info || VG_(clo_read_var_info))) {
2575       UWord nVars = 0;
2576       Word  j;
2577       if (di->varinfo) {
2578          for (j = 0; j < VG_(sizeXA)(di->varinfo); j++) {
2579             OSet* /* of DiAddrRange */ scope
2580                = *(OSet**)VG_(indexXA)(di->varinfo, j);
2581             vg_assert(scope);
2582             VG_(OSetGen_ResetIter)( scope );
2583             while (True) {
2584                DiAddrRange* range  = VG_(OSetGen_Next)( scope );
2585                if (!range) break;
2586                vg_assert(range->vars);
2587                Word w = VG_(sizeXA)(range->vars);
2588                vg_assert(w >= 0);
2589                if (0) VG_(printf)("range %#lx %#lx %ld\n",
2590                                   range->aMin, range->aMax, w);
2591                nVars += (UWord)w;
2592             }
2593          }
2594       }
2595       VG_(umsg)("VARINFO: %7lu vars   %7ld text_size   %s\n",
2596                 nVars, di->text_size, di->fsm.filename);
2597    }
2598    /* TOPLEVEL */
2599 
2600   out:
2601    {
2602       SysRes m_res;
2603       /* Last, but not least, heave the image(s) back overboard. */
2604       if (dimage) {
2605          m_res = VG_(am_munmap_valgrind) ( dimage, n_dimage );
2606          vg_assert(!sr_isError(m_res));
2607       }
2608       m_res = VG_(am_munmap_valgrind) ( oimage, n_oimage );
2609       vg_assert(!sr_isError(m_res));
2610       return res;
2611    } /* out: */
2612 
2613    /* NOTREACHED */
2614 }
2615 
2616 #endif // defined(VGO_linux)
2617 
2618 /*--------------------------------------------------------------------*/
2619 /*--- end                                                          ---*/
2620 /*--------------------------------------------------------------------*/
2621