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