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