readelf.c revision 092b6268cc4a38ae9ee41d1e3355937536ddc579
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 %010p, %ssz %4d  %s\n",
169               sym_svma, space, sym->st_size,
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 -- %p .. %p outside .text svma range %p .. %p\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 -- %p .. %p 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 (%d 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) [%4d]:          "
566                        "  val %010p, sz %4d  %s\n",
567                        is_text ? 't' : 'd',
568                        i, (void*)risym.addr, (Int)risym.size,
569                           (HChar*)risym.name
570            );
571         }
572
573      }
574   }
575}
576
577
578/* Read an ELF symbol table (normal or dynamic).  This one is for
579   ppc64-linux, which requires special treatment. */
580
581typedef
582   struct {
583      Addr   addr;
584      UChar* name;
585   }
586   TempSymKey;
587
588typedef
589   struct {
590      TempSymKey key;
591      Addr       tocptr;
592      Int        size;
593      Bool       from_opd;
594      Bool       is_text;
595   }
596   TempSym;
597
598static Word cmp_TempSymKey ( TempSymKey* key1, TempSym* elem2 ) {
599   if (key1->addr < elem2->key.addr) return -1;
600   if (key1->addr > elem2->key.addr) return 1;
601   return (Word)VG_(strcmp)(key1->name, elem2->key.name);
602}
603
604static
605__attribute__((unused)) /* not referred to on all targets */
606void read_elf_symtab__ppc64_linux(
607        struct _DebugInfo* di, UChar* tab_name,
608        ElfXX_Sym* symtab_img, SizeT symtab_szB,
609        UChar*     strtab_img, SizeT strtab_szB,
610        UChar*     opd_img /* ppc64-linux only */
611     )
612{
613   Word        i;
614   Int         old_size;
615   Addr        sym_svma, sym_avma_really;
616   Char       *sym_name, *sym_name_really;
617   Int         sym_size;
618   Addr        sym_tocptr, old_tocptr;
619   Bool        from_opd, modify_size, modify_tocptr, is_text;
620   DiSym       risym;
621   ElfXX_Sym  *sym;
622   OSet       *oset;
623   TempSymKey  key;
624   TempSym    *elem;
625   TempSym    *prev;
626
627   if (strtab_img == NULL || symtab_img == NULL) {
628      Char buf[80];
629      vg_assert(VG_(strlen)(tab_name) < 40);
630      VG_(sprintf)(buf, "   object doesn't have a %s", tab_name);
631      ML_(symerr)(di, False, buf);
632      return;
633   }
634
635   TRACE_SYMTAB("\n--- Reading (ELF, ppc64-linux) %s (%d entries) ---\n",
636                tab_name, symtab_szB/sizeof(ElfXX_Sym) );
637
638   oset = VG_(OSetGen_Create)( offsetof(TempSym,key),
639                               (OSetCmp_t)cmp_TempSymKey,
640                               ML_(dinfo_zalloc), ML_(dinfo_free) );
641   vg_assert(oset);
642
643   /* Perhaps should start at i = 1; ELF docs suggest that entry
644      0 always denotes 'unknown symbol'. */
645   for (i = 1; i < (Word)(symtab_szB/sizeof(ElfXX_Sym)); i++) {
646      sym      = & symtab_img[i];
647      sym_name = (Char*)(strtab_img + sym->st_name);
648      sym_svma = sym->st_value;
649
650      if (di->trace_symtab)
651         show_raw_elf_symbol(i, sym, sym_name, sym_svma, True);
652
653      if (get_elf_symbol_info(di, sym, sym_name, sym_svma,
654                              opd_img, di->text_bias,
655                              &sym_name_really,
656                              &sym_avma_really,
657                              &sym_size,
658                              &sym_tocptr,
659                              &from_opd, &is_text)) {
660
661         /* Check if we've seen this (name,addr) key before. */
662         key.addr = sym_avma_really;
663         key.name = sym_name_really;
664         prev = VG_(OSetGen_Lookup)( oset, &key );
665
666         if (prev) {
667
668            /* Seen it before.  Fold in whatever new info we can. */
669            modify_size   = False;
670            modify_tocptr = False;
671            old_size   = 0;
672            old_tocptr = 0;
673
674            if (prev->from_opd && !from_opd
675                && (prev->size == 24 || prev->size == 16)
676                && sym_size != prev->size) {
677               /* Existing one is an opd-redirect, with a bogus size,
678                  so the only useful new fact we have is the real size
679                  of the symbol. */
680               modify_size = True;
681               old_size = prev->size;
682               prev->size = sym_size;
683            }
684            else
685            if (!prev->from_opd && from_opd
686                && (sym_size == 24 || sym_size == 16)) {
687               /* Existing one is non-opd, new one is opd.  What we
688                  can acquire from the new one is the TOC ptr to be
689                  used.  Since the existing sym is non-toc, it
690                  shouldn't currently have an known TOC ptr. */
691               vg_assert(prev->tocptr == 0);
692               modify_tocptr = True;
693               old_tocptr = prev->tocptr;
694               prev->tocptr = sym_tocptr;
695            }
696            else {
697               /* ignore. can we do better here? */
698            }
699
700            /* Only one or the other is possible (I think) */
701            vg_assert(!(modify_size && modify_tocptr));
702
703            if (modify_size && di->trace_symtab) {
704               VG_(printf)("    modify (old sz %4d)    "
705                           " val %010p, toc %010p, sz %4d  %s\n",
706                           old_size,
707                           (void*) prev->key.addr,
708                           (void*) prev->tocptr,
709                           (Int)   prev->size,
710                           (HChar*)prev->key.name
711               );
712            }
713            if (modify_tocptr && di->trace_symtab) {
714               VG_(printf)("    modify (upd tocptr)     "
715                           " val %010p, toc %010p, sz %4d  %s\n",
716                            (void*) prev->key.addr,
717                            (void*) prev->tocptr,
718                            (Int)   prev->size,
719                            (HChar*)prev->key.name
720               );
721            }
722
723         } else {
724
725            /* A new (name,addr) key.  Add and continue. */
726            elem = VG_(OSetGen_AllocNode)(oset, sizeof(TempSym));
727            vg_assert(elem);
728            elem->key      = key;
729            elem->tocptr   = sym_tocptr;
730            elem->size     = sym_size;
731            elem->from_opd = from_opd;
732            elem->is_text  = is_text;
733            VG_(OSetGen_Insert)(oset, elem);
734            if (di->trace_symtab) {
735               VG_(printf)("   to-oset [%4d]:          "
736                           "  val %010p, toc %010p, sz %4d  %s\n",
737                           i, (void*) elem->key.addr,
738                              (void*) elem->tocptr,
739                              (Int)   elem->size,
740                              (HChar*)elem->key.name
741               );
742            }
743
744         }
745      }
746   }
747
748   /* All the syms that matter are in the oset.  Now pull them out,
749      build a "standard" symbol table, and nuke the oset. */
750
751   i = 0;
752   VG_(OSetGen_ResetIter)( oset );
753
754   while ( (elem = VG_(OSetGen_Next)(oset)) ) {
755      risym.addr   = elem->key.addr;
756      risym.size   = elem->size;
757      risym.name   = ML_(addStr) ( di, elem->key.name, -1 );
758      risym.tocptr = elem->tocptr;
759      risym.isText = elem->is_text;
760      vg_assert(risym.name != NULL);
761
762      ML_(addSym) ( di, &risym );
763      if (di->trace_symtab) {
764         VG_(printf)("    rec(%c) [%4d]:          "
765                     "   val %010p, toc %010p, sz %4d  %s\n",
766                     risym.isText ? 't' : 'd',
767                     i, (void*) risym.addr,
768                        (void*) risym.tocptr,
769                        (Int)   risym.size,
770                        (HChar*)risym.name
771               );
772      }
773      i++;
774   }
775
776   VG_(OSetGen_Destroy)( oset );
777}
778
779
780/*
781 * This routine for calculating the CRC for a separate debug file
782 * is GPLed code borrowed from GNU binutils.
783 */
784static UInt
785calc_gnu_debuglink_crc32(UInt crc, const UChar *buf, Int len)
786{
787  static const UInt crc32_table[256] =
788    {
789      0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
790      0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
791      0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
792      0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
793      0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
794      0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
795      0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
796      0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
797      0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
798      0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
799      0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
800      0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
801      0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
802      0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
803      0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
804      0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
805      0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
806      0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
807      0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
808      0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
809      0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
810      0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
811      0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
812      0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
813      0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
814      0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
815      0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
816      0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
817      0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
818      0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
819      0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
820      0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
821      0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
822      0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
823      0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
824      0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
825      0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
826      0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
827      0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
828      0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
829      0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
830      0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
831      0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
832      0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
833      0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
834      0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
835      0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
836      0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
837      0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
838      0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
839      0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
840      0x2d02ef8d
841    };
842  const UChar *end;
843
844  crc = ~crc & 0xffffffff;
845  for (end = buf + len; buf < end; ++ buf)
846    crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);
847  return ~crc & 0xffffffff;;
848}
849
850/*
851 * Try and open a separate debug file, ignoring any where the CRC does
852 * not match the value from the main object file.
853 */
854static
855Addr open_debug_file( Char* name, UInt crc, /*OUT*/UWord* size )
856{
857   SysRes fd, sres;
858   struct vki_stat stat_buf;
859   UInt calccrc;
860
861   fd = VG_(open)(name, VKI_O_RDONLY, 0);
862   if (fd.isError)
863      return 0;
864
865   if (VG_(fstat)(fd.res, &stat_buf) != 0) {
866      VG_(close)(fd.res);
867      return 0;
868   }
869
870   if (VG_(clo_verbosity) > 1)
871      VG_(message)(Vg_DebugMsg, "Reading debug info from %s ..", name);
872
873   *size = stat_buf.st_size;
874
875   sres = VG_(am_mmap_file_float_valgrind)
876             ( *size, VKI_PROT_READ, fd.res, 0 );
877
878   VG_(close)(fd.res);
879
880   if (sres.isError)
881      return 0;
882
883   calccrc = calc_gnu_debuglink_crc32(0, (UChar*)sres.res, *size);
884   if (calccrc != crc) {
885      SysRes res = VG_(am_munmap_valgrind)(sres.res, *size);
886      vg_assert(!res.isError);
887      if (VG_(clo_verbosity) > 1)
888         VG_(message)(Vg_DebugMsg,
889            ".. CRC mismatch (computed %08x wanted %08x)", calccrc, crc);
890      return 0;
891   }
892
893   return sres.res;
894}
895
896/*
897 * Try to find a separate debug file for a given object file.
898 */
899static
900Addr find_debug_file( struct _DebugInfo* di,
901                      Char* objpath, Char* debugname,
902                      UInt crc, /*OUT*/UWord* size )
903{
904   Char *objdir = ML_(dinfo_strdup)(objpath);
905   Char *objdirptr;
906   Char *debugpath;
907   Addr addr = 0;
908
909   if ((objdirptr = VG_(strrchr)(objdir, '/')) != NULL)
910      *objdirptr = '\0';
911
912   debugpath = ML_(dinfo_zalloc)(
913                  VG_(strlen)(objdir) + VG_(strlen)(debugname) + 32);
914
915   VG_(sprintf)(debugpath, "%s/%s", objdir, debugname);
916
917   if ((addr = open_debug_file(debugpath, crc, size)) == 0) {
918      VG_(sprintf)(debugpath, "%s/.debug/%s", objdir, debugname);
919      if ((addr = open_debug_file(debugpath, crc, size)) == 0) {
920         VG_(sprintf)(debugpath, "/usr/lib/debug%s/%s", objdir, debugname);
921         addr = open_debug_file(debugpath, crc, size);
922      }
923   }
924
925   if (addr) {
926      TRACE_SYMTAB("\n");
927      TRACE_SYMTAB("------ Found a debuginfo file: %s\n", debugpath);
928   }
929
930   ML_(dinfo_free)(debugpath);
931   ML_(dinfo_free)(objdir);
932
933   return addr;
934}
935
936
937static Bool contained_within ( Addr outer, UWord n_outer,
938                               Addr inner, UWord n_inner )
939{
940   if (n_outer == 0 || n_inner == 0)
941      return False;
942   /* Simplistic .. assumes no wraparound (reasonably enough) */
943   if (inner >= outer && inner+n_inner <= outer+n_outer)
944      return True;
945   return False;
946}
947
948static void* INDEX_BIS ( void* base, Word index, Word scale ) {
949   return (void*)( ((UChar*)base) + index * scale );
950}
951
952static Addr round_Addr_upwards ( Addr a, UInt align )
953{
954   if (align > 0) {
955      vg_assert(-1 != VG_(log2)(align));
956      a = VG_ROUNDUP(a, align);
957   }
958   return a;
959}
960
961
962/* Find the file offset corresponding to SVMA by using the program
963   headers.  This is taken from binutils-2.17/binutils/readelf.c
964   offset_from_vma(). */
965static
966Word file_offset_from_svma ( /*OUT*/Bool* ok,
967                             Addr         svma,
968                             ElfXX_Phdr*  phdr_img,
969                             Word         phdr_nent,
970                             Word         phdr_ent_szB )
971{
972   Word        i;
973   ElfXX_Phdr* seg;
974   for (i = 0; i < phdr_nent; i++) {
975      seg = INDEX_BIS( phdr_img, i, phdr_ent_szB );
976      if (seg->p_type != PT_LOAD)
977         continue;
978      if (svma >= (seg->p_vaddr & -seg->p_align)
979          && svma + 1 <= seg->p_vaddr + seg->p_filesz) {
980         *ok = True;
981         return svma - seg->p_vaddr + seg->p_offset;
982      }
983   }
984   *ok = False;
985   return 0;
986}
987
988/* The central function for reading ELF debug info.  For the
989   object/exe specified by the DebugInfo, find ELF sections, then read
990   the symbols, line number info, file name info, CFA (stack-unwind
991   info) and anything else we want, into the tables within the
992   supplied DebugInfo.
993*/
994Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di )
995{
996   Bool          res, ok;
997   SysRes        fd, sres;
998   Word          i;
999
1000   /* Image addresses for the ELF file we're working with. */
1001   Addr          oimage   = 0;
1002   UWord         n_oimage = 0;
1003
1004   /* Ditto for any ELF debuginfo file that we might happen to load. */
1005   Addr          dimage   = 0;
1006   UWord         n_dimage = 0;
1007
1008   /* ELF header for the main file.  Should == oimage since is at
1009      start of file. */
1010   ElfXX_Ehdr* ehdr_img = NULL;
1011
1012   /* Program header table image addr, # entries, entry size */
1013   ElfXX_Phdr* phdr_img     = NULL;
1014   UWord       phdr_nent    = 0;
1015   UWord       phdr_ent_szB = 0;
1016
1017   /* Section header image addr, # entries, entry size.  Also the
1018      associated string table. */
1019   ElfXX_Shdr* shdr_img        = NULL;
1020   UWord       shdr_nent       = 0;
1021   UWord       shdr_ent_szB    = 0;
1022   UChar*      shdr_strtab_img = NULL;
1023
1024   /* To do with figuring out where .sbss is relative to .bss.  A
1025      kludge at the best of times. */
1026   SizeT sbss_size;
1027   Addr  sbss_svma;
1028   UInt  bss_align;
1029   UInt  sbss_align;
1030   UInt  data_align;
1031   SizeT bss_totsize;
1032   Addr  gen_bss_lowest_svma;
1033
1034   vg_assert(di);
1035   vg_assert(di->have_rx_map == True);
1036   vg_assert(di->have_rw_map == True);
1037   vg_assert(di->rx_map_size > 0);
1038   vg_assert(di->rw_map_size > 0);
1039   vg_assert(di->have_dinfo == False);
1040   vg_assert(di->filename);
1041   vg_assert(!di->memname);
1042   vg_assert(!di->symtab);
1043   vg_assert(!di->loctab);
1044   vg_assert(!di->cfsi);
1045   vg_assert(!di->cfsi_exprs);
1046   vg_assert(!di->strchunks);
1047   vg_assert(!di->soname);
1048
1049   /* If these don't hold true, it means that m_syswrap/m_aspacemgr
1050      managed to do a mapping where the start isn't page aligned.
1051      Which sounds pretty bogus to me. */
1052   vg_assert(VG_IS_PAGE_ALIGNED(di->rx_map_avma));
1053   vg_assert(VG_IS_PAGE_ALIGNED(di->rw_map_avma));
1054
1055   /* ----------------------------------------------------------
1056      At this point, there is very little information in the
1057      DebugInfo.  We only know that something that looks like an ELF
1058      file has been mapped rx-ishly as recorded with the di->*rx_map*
1059      fields and has also been mapped rw-ishly as recorded with the
1060      di->*rw_map* fields.  First we examine the file's ELF Program
1061      Header, and, by comparing that against the di->*r{w,x}_map*
1062      info, try to figure out the AVMAs for the sections we care
1063      about, that should have been mapped: text, data, sdata, bss got,
1064      plt, and toc.
1065      ---------------------------------------------------------- */
1066
1067   oimage = (Addr)NULL;
1068   if (VG_(clo_verbosity) > 1 || VG_(clo_trace_redir))
1069      VG_(message)(Vg_DebugMsg, "Reading syms from %s (%p)",
1070                                di->filename, di->rx_map_avma );
1071
1072   /* mmap the object image aboard, so that we can read symbols and
1073      line number info out of it.  It will be munmapped immediately
1074      thereafter; it is only aboard transiently. */
1075
1076   fd = VG_(open)(di->filename, VKI_O_RDONLY, 0);
1077   if (fd.isError) {
1078      ML_(symerr)(di, True, "Can't open .so/.exe to read symbols?!");
1079      return False;
1080   }
1081
1082   n_oimage = VG_(fsize)(fd.res);
1083   if (n_oimage <= 0) {
1084      ML_(symerr)(di, True, "Can't stat .so/.exe (to determine its size)?!");
1085      VG_(close)(fd.res);
1086      return False;
1087   }
1088
1089   sres = VG_(am_mmap_file_float_valgrind)
1090             ( n_oimage, VKI_PROT_READ, fd.res, 0 );
1091
1092   VG_(close)(fd.res);
1093
1094   if (sres.isError) {
1095      VG_(message)(Vg_UserMsg, "warning: mmap failed on %s", di->filename );
1096      VG_(message)(Vg_UserMsg, "         no symbols or debug info loaded" );
1097      return False;
1098   }
1099
1100   oimage = sres.res;
1101   /* Check against wraparound.  am_mmap_file_float_valgrind should
1102      not produce a wrapped-around mapping. */
1103   vg_assert(n_oimage > 0);
1104   vg_assert(oimage + n_oimage > oimage);
1105
1106   if (0) {
1107      VG_(printf)("read_elf_debug_info: OIMAGE = %p - %p\n",
1108                  (void*)oimage, (void*)(oimage + (UWord)n_oimage));
1109   }
1110
1111   /* Ok, the object image is safely in oimage[0 .. n_oimage-1].  Now
1112      verify that it is a valid ELF .so or executable image. */
1113   res      = False;
1114   ok       = (n_oimage >= sizeof(ElfXX_Ehdr));
1115   ehdr_img = (ElfXX_Ehdr*)oimage;
1116
1117   if (ok)
1118      ok &= ML_(is_elf_object_file)(ehdr_img, n_oimage);
1119
1120   if (!ok) {
1121      ML_(symerr)(di, True, "Invalid ELF Header");
1122      goto out;
1123   }
1124
1125   /* Find where the program and section header tables are, and give
1126      up if either is missing or outside the image (bogus). */
1127   phdr_img     = (ElfXX_Phdr*)( ((UChar*)ehdr_img) + ehdr_img->e_phoff );
1128   phdr_nent    = ehdr_img->e_phnum;
1129   phdr_ent_szB = ehdr_img->e_phentsize;
1130
1131   shdr_img     = (ElfXX_Shdr*)( ((UChar*)ehdr_img) + ehdr_img->e_shoff );
1132   shdr_nent    = ehdr_img->e_shnum;
1133   shdr_ent_szB = ehdr_img->e_shentsize;
1134
1135   TRACE_SYMTAB("------ Basic facts about the object ------\n");
1136   TRACE_SYMTAB("object: img %p n_oimage %ld\n",
1137               (void*)oimage, n_oimage);
1138   TRACE_SYMTAB("phdr:   img %p nent %ld ent_szB %ld\n",
1139               phdr_img, phdr_nent, phdr_ent_szB);
1140   TRACE_SYMTAB("shdr:   img %p nent %ld ent_szB %ld\n",
1141               shdr_img, shdr_nent, shdr_ent_szB);
1142
1143   if (phdr_nent == 0
1144       || !contained_within(
1145             oimage, n_oimage,
1146             (Addr)phdr_img, phdr_nent * phdr_ent_szB)) {
1147      ML_(symerr)(di, True, "Missing or invalid ELF Program Header Table");
1148      goto out;
1149   }
1150
1151   if (shdr_nent == 0
1152       || !contained_within(
1153             oimage, n_oimage,
1154             (Addr)shdr_img, shdr_nent * shdr_ent_szB)) {
1155      ML_(symerr)(di, True, "Missing or invalid ELF Section Header Table");
1156      goto out;
1157   }
1158
1159   /* Also find the section header's string table, and validate. */
1160   /* checked previously by is_elf_object_file: */
1161   vg_assert( ehdr_img->e_shstrndx != SHN_UNDEF );
1162
1163   shdr_strtab_img
1164      = (UChar*)( ((UChar*)ehdr_img)
1165                  + shdr_img[ehdr_img->e_shstrndx].sh_offset);
1166   if (!contained_within( oimage, n_oimage,
1167                          (Addr)shdr_strtab_img,
1168                          1/*bogus, but we don't know the real size*/ )) {
1169      ML_(symerr)(di, True, "Invalid ELF Section Header String Table");
1170      goto out;
1171   }
1172
1173   TRACE_SYMTAB("shdr:   string table at %p\n", shdr_strtab_img );
1174
1175   /* Do another amazingly tedious thing: find out the .soname for
1176      this object.  Apparently requires looking through the program
1177      header table. */
1178   TRACE_SYMTAB("\n");
1179   TRACE_SYMTAB("------ Looking for the soname ------\n");
1180   vg_assert(di->soname == NULL);
1181   {
1182      ElfXX_Addr prev_svma = 0;
1183
1184      for (i = 0; i < phdr_nent; i++) {
1185         ElfXX_Phdr* phdr = INDEX_BIS( phdr_img, i, phdr_ent_szB );
1186
1187         /* Make sure the PT_LOADable entries are in order */
1188         if (phdr->p_type == PT_LOAD) {
1189            TRACE_SYMTAB("PT_LOAD in order?: %p %p\n",
1190                         prev_svma, phdr->p_vaddr);
1191            if (phdr->p_vaddr < prev_svma) {
1192               ML_(symerr)(di, True,
1193                           "ELF Program Headers are not in ascending order");
1194               goto out;
1195            }
1196            prev_svma = phdr->p_vaddr;
1197         }
1198
1199         /* Try to get the soname.  If there isn't one, use "NONE".
1200            The seginfo needs to have some kind of soname in order to
1201            facilitate writing redirect functions, since all redirect
1202            specifications require a soname (pattern). */
1203         if (phdr->p_type == PT_DYNAMIC && di->soname == NULL) {
1204            ElfXX_Dyn* dyn_img = (ElfXX_Dyn*)( ((UChar*)ehdr_img)
1205                                               + phdr->p_offset);
1206            Word   stroff = -1;
1207            UChar* strtab = NULL;
1208            Word   j;
1209            for (j = 0; dyn_img[j].d_tag != DT_NULL; j++) {
1210               switch (dyn_img[j].d_tag) {
1211                  case DT_SONAME: {
1212                     stroff = dyn_img[j].d_un.d_val;
1213                     break;
1214                  }
1215                  case DT_STRTAB: {
1216                     Bool ok2 = False;
1217                     Word offset = file_offset_from_svma(
1218                                      &ok2,
1219                                      dyn_img[j].d_un.d_ptr,
1220                                      phdr_img,
1221                                      phdr_nent, phdr_ent_szB
1222                                   );
1223                     if (ok2 && strtab == NULL) {
1224                        vg_assert(offset >= 0 && offset <= n_oimage);
1225                        strtab = ((UChar*)ehdr_img) + offset;
1226                     }
1227                     break;
1228                  }
1229                  default:
1230                     break;
1231               }
1232            }
1233            if (stroff != -1 && strtab != NULL) {
1234               TRACE_SYMTAB("Found soname = %s\n", strtab+stroff);
1235               di->soname = ML_(dinfo_strdup)(strtab+stroff);
1236            }
1237         }
1238      } /* for (i = 0; i < phdr_nent; i++) ... */
1239   } /* look for the soname */
1240
1241   /* If, after looking at all the program headers, we still didn't
1242      find a soname, add a fake one. */
1243   if (di->soname == NULL) {
1244      TRACE_SYMTAB("No soname found; using (fake) \"NONE\"\n");
1245      di->soname = "NONE";
1246   }
1247
1248   /*SizeT*/ sbss_size  = 0;
1249   /*Addr */ sbss_svma  = 0;
1250   /*UInt */ bss_align  = 0;
1251   /*UInt */ sbss_align = 0;
1252
1253   /* UInt */  data_align = 0;
1254   /* SizeT */ bss_totsize = 0;
1255   /* Addr */  gen_bss_lowest_svma = ~((Addr)0);
1256
1257   /* Now read the section table. */
1258   TRACE_SYMTAB("\n");
1259   TRACE_SYMTAB("------ Examining the section headers "
1260                "and program headers ------\n");
1261   TRACE_SYMTAB("rx: at %p are mapped foffsets %ld .. %ld\n",
1262               di->rx_map_avma,
1263               di->rx_map_foff, di->rx_map_foff + di->rx_map_size - 1 );
1264   TRACE_SYMTAB("rw: at %p are mapped foffsets %ld .. %ld\n",
1265               di->rw_map_avma,
1266               di->rw_map_foff, di->rw_map_foff + di->rw_map_size - 1 );
1267
1268   for (i = 0; i < shdr_nent; i++) {
1269      ElfXX_Shdr* shdr = INDEX_BIS( shdr_img, i, shdr_ent_szB );
1270      UChar* name = shdr_strtab_img + shdr->sh_name;
1271      Addr   svma = shdr->sh_addr;
1272      OffT   foff = shdr->sh_offset;
1273      UWord  size = shdr->sh_size;
1274      UInt   alyn = shdr->sh_addralign;
1275      Bool   bits = !(shdr->sh_type == SHT_NOBITS);
1276      Bool   inrx = foff >= di->rx_map_foff
1277                    && foff < di->rx_map_foff + di->rx_map_size;
1278      Bool   inrw = foff >= di->rw_map_foff
1279                    && foff < di->rw_map_foff + di->rw_map_size;
1280
1281      TRACE_SYMTAB(" [sec %2ld]  %s %s  al%2u  foff %6ld .. %6ld  "
1282                  "  svma %p  name \"%s\"\n",
1283                  i, inrx ? "rx" : "  ", inrw ? "rw" : "  ", alyn,
1284                  foff, foff+size-1, (void*)svma, name );
1285
1286      /* Check for sane-sized segments.  SHT_NOBITS sections have zero
1287         size in the file. */
1288      if ((foff >= n_oimage) || (foff + (bits ? size : 0) > n_oimage)) {
1289         ML_(symerr)(di, True, "ELF Section extends beyond image end");
1290         goto out;
1291      }
1292
1293      /* Check for a sane alignment value. */
1294      if (alyn > 0 && -1 == VG_(log2)(alyn)) {
1295         ML_(symerr)(di, True, "ELF Section contains invalid "
1296                               ".sh_addralign value");
1297         goto out;
1298      }
1299
1300#     define BAD(_secname)                                 \
1301         do { ML_(symerr)(di, True,                        \
1302                          "Can't make sense of " _secname  \
1303                          " section mapping");             \
1304              goto out;                                    \
1305         } while (0)
1306
1307      /* Find avma-s for: .text .data .sdata .bss .plt .got .opd
1308         and .eh_frame */
1309
1310      /* Accept .text where mapped as rx (code) */
1311      if (0 == VG_(strcmp)(name, ".text")) {
1312         if (inrx && size > 0 && !di->text_present) {
1313            di->text_present = True;
1314            di->text_svma = svma;
1315            di->text_avma = di->rx_map_avma + foff - di->rx_map_foff;
1316            di->text_size = size;
1317            di->text_bias = di->text_avma - svma;
1318            TRACE_SYMTAB("acquiring .text svma = %p .. %p\n",
1319                         di->text_svma,
1320                         di->text_svma + di->text_size - 1);
1321            TRACE_SYMTAB("acquiring .text avma = %p .. %p\n",
1322                         di->text_avma,
1323                         di->text_avma + di->text_size - 1);
1324            TRACE_SYMTAB("acquiring .text bias = %p\n", di->text_bias);
1325         } else {
1326            BAD(".text");
1327         }
1328      }
1329
1330      /* Accept .data where mapped as rw (data), even if zero-sized */
1331      if (0 == VG_(strcmp)(name, ".data")) {
1332         if (inrw && size >= 0 && !di->data_present) {
1333            if (alyn > data_align)
1334               data_align = alyn;
1335            di->data_present = True;
1336            di->data_svma = svma;
1337            di->data_avma = di->rw_map_avma + foff - di->rw_map_foff;
1338            di->data_size = size;
1339            di->data_bias = di->data_avma - svma;
1340            TRACE_SYMTAB("acquiring .data svma = %p .. %p\n",
1341                         di->data_svma,
1342                         di->data_svma + di->data_size - 1);
1343            TRACE_SYMTAB("acquiring .data avma = %p .. %p\n",
1344                         di->data_avma,
1345                         di->data_avma + di->data_size - 1);
1346            TRACE_SYMTAB("acquiring .data bias = %p\n", di->data_bias);
1347         } else {
1348            BAD(".data");
1349         }
1350      }
1351
1352      /* Accept .sdata where mapped as rw (data) */
1353      if (0 == VG_(strcmp)(name, ".sdata")) {
1354         if (inrw && size > 0 && !di->sdata_present) {
1355            if (alyn > data_align)
1356               data_align = alyn;
1357            di->sdata_present = True;
1358            di->sdata_svma = svma;
1359            di->sdata_avma = di->rw_map_avma + foff - di->rw_map_foff;
1360            di->sdata_size = size;
1361            di->sdata_bias = di->sdata_avma - svma;
1362            TRACE_SYMTAB("acquiring .sdata svma = %p .. %p\n",
1363                         di->sdata_svma,
1364                         di->sdata_svma + di->sdata_size - 1);
1365            TRACE_SYMTAB("acquiring .sdata avma = %p .. %p\n",
1366                         di->sdata_avma,
1367                         di->sdata_avma + di->sdata_size - 1);
1368            TRACE_SYMTAB("acquiring .sdata bias = %p\n", di->sdata_bias);
1369         } else {
1370            BAD(".sdata");
1371         }
1372      }
1373
1374      /* Accept .bss where mapped as rw (data), even if zero-sized */
1375      if (0 == VG_(strcmp)(name, ".bss")) {
1376         if (inrw && size >= 0 && !di->bss_present) {
1377            bss_totsize += round_Addr_upwards(size, alyn);
1378            if (svma < gen_bss_lowest_svma)
1379               gen_bss_lowest_svma = svma;
1380            TRACE_SYMTAB("increasing total bss-like size to %ld\n",
1381                         bss_totsize);
1382            di->bss_present = True;
1383            di->bss_svma = svma;
1384            di->bss_avma = di->rw_map_avma + foff - di->rw_map_foff;
1385            di->bss_size = size;
1386            di->bss_bias = di->bss_avma - svma;
1387            bss_align = alyn;
1388            TRACE_SYMTAB("acquiring .bss svma = %p .. %p\n",
1389                         di->bss_svma,
1390                         di->bss_svma + di->bss_size - 1);
1391            TRACE_SYMTAB("acquiring .bss avma = %p .. %p\n",
1392                         di->bss_avma,
1393                         di->bss_avma + di->bss_size - 1);
1394            TRACE_SYMTAB("acquiring .bss bias = %p\n", di->bss_bias);
1395         } else
1396
1397         /* Now one from the wtf?! department ... */
1398         if (inrx && (!inrw) && size >= 0 && !di->bss_present) {
1399            /* File contains a .bss, but it got mapped as rx only.
1400               This is very strange.  For now, just pretend we didn't
1401               see it :-) */
1402            di->bss_present = False;
1403            di->bss_svma = 0;
1404            di->bss_avma = 0;
1405            di->bss_size = 0;
1406            di->bss_bias = 0;
1407            bss_align = 0;
1408            if (!VG_(clo_xml)) {
1409               VG_(message)(Vg_UserMsg, "Warning: the following file's .bss is "
1410                                       "mapped r-x only - ignoring .bss syms");
1411               VG_(message)(Vg_UserMsg,   " %s", di->filename
1412                                                    ? di->filename
1413                                                    : (UChar*)"(null?!)" );
1414            }
1415         } else
1416
1417         if ((!inrw) && (!inrx) && size > 0 && !di->bss_present) {
1418            /* File contains a .bss, but it didn't get mapped.  Ignore. */
1419            di->bss_present = False;
1420            di->bss_svma = 0;
1421            di->bss_avma = 0;
1422            di->bss_size = 0;
1423            di->bss_bias = 0;
1424            bss_align = 0;
1425         } else {
1426            BAD(".bss");
1427         }
1428      }
1429
1430      /* Accept .sbss where mapped as rw (data) */
1431      if (0 == VG_(strcmp)(name, ".sbss")) {
1432         if (inrw && size > 0 && sbss_size == 0) {
1433            bss_totsize += round_Addr_upwards(size, alyn);
1434            if (svma < gen_bss_lowest_svma)
1435               gen_bss_lowest_svma = svma;
1436            TRACE_SYMTAB("increasing total bss-like size to %ld\n",
1437                         bss_totsize);
1438            sbss_size  = size;
1439            sbss_svma  = svma;
1440            sbss_align = alyn;
1441         } else {
1442            BAD(".sbss");
1443         }
1444      }
1445
1446      /* Accept .dynbss where mapped as rw (data) */
1447      if (0 == VG_(strcmp)(name, ".dynbss")) {
1448	if (inrw && size > 0 /* && sbss_size == 0*/) {
1449           bss_totsize += round_Addr_upwards(size, alyn);
1450           if (svma < gen_bss_lowest_svma)
1451              gen_bss_lowest_svma = svma;
1452           TRACE_SYMTAB("increasing total bss-like size to %ld\n",
1453                        bss_totsize);
1454         } else {
1455            BAD(".dynbss");
1456         }
1457      }
1458
1459      /* Accept .got where mapped as rw (data) */
1460      if (0 == VG_(strcmp)(name, ".got")) {
1461         if (inrw && size > 0 && !di->got_present) {
1462            di->got_present = True;
1463            di->got_avma = di->rw_map_avma + foff - di->rw_map_foff;
1464            di->got_size = size;
1465            TRACE_SYMTAB("acquiring .got avma = %p\n", di->got_avma);
1466         } else {
1467            BAD(".got");
1468         }
1469      }
1470
1471      /* Accept .got.plt where mapped as rw (data) */
1472      if (0 == VG_(strcmp)(name, ".got.plt")) {
1473         if (inrw && size > 0 && !di->gotplt_present) {
1474            di->gotplt_present = True;
1475            di->gotplt_avma = di->rw_map_avma + foff - di->rw_map_foff;
1476            di->gotplt_size = size;
1477            TRACE_SYMTAB("acquiring .got.plt avma = %p\n", di->gotplt_avma);
1478         } else {
1479            BAD(".got.plt");
1480         }
1481      }
1482
1483      /* PLT is different on different platforms, it seems. */
1484#     if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
1485      /* Accept .plt where mapped as rx (code) */
1486      if (0 == VG_(strcmp)(name, ".plt")) {
1487         if (inrx && size > 0 && !di->plt_present) {
1488            di->plt_present = True;
1489            di->plt_avma = di->rx_map_avma + foff - di->rx_map_foff;
1490            di->plt_size = size;
1491            TRACE_SYMTAB("acquiring .plt avma = %p\n", di->plt_avma);
1492         } else {
1493            BAD(".plt");
1494         }
1495      }
1496#     elif defined(VGP_ppc32_linux)
1497      /* Accept .plt where mapped as rw (data) */
1498      if (0 == VG_(strcmp)(name, ".plt")) {
1499         if (inrw && size > 0 && !di->plt_present) {
1500            di->plt_present = True;
1501            di->plt_avma = di->rw_map_avma + foff - di->rw_map_foff;
1502            di->plt_size = size;
1503            TRACE_SYMTAB("acquiring .plt avma = %p\n", di->plt_avma);
1504         } else {
1505            BAD(".plt");
1506         }
1507      }
1508#     elif defined(VGP_ppc64_linux)
1509      /* Accept .plt where mapped as rw (data), or unmapped */
1510      if (0 == VG_(strcmp)(name, ".plt")) {
1511         if (inrw && size > 0 && !di->plt_present) {
1512            di->plt_present = True;
1513            di->plt_avma = di->rw_map_avma + foff - di->rw_map_foff;
1514            di->plt_size = size;
1515            TRACE_SYMTAB("acquiring .plt avma = %p\n", di->plt_avma);
1516         } else
1517         if ((!inrw) && (!inrx) && size > 0 && !di->plt_present) {
1518            /* File contains a .plt, but it didn't get mapped.
1519               Presumably it is not required on this platform.  At
1520               least don't reject the situation as invalid. */
1521            di->plt_present = True;
1522            di->plt_avma = 0;
1523            di->plt_size = 0;
1524         } else {
1525            BAD(".plt");
1526         }
1527      }
1528#     else
1529#       error "Unsupported platform"
1530#     endif
1531
1532      /* Accept .opd where mapped as rw (data) */
1533      if (0 == VG_(strcmp)(name, ".opd")) {
1534         if (inrw && size > 0 && !di->opd_present) {
1535            di->opd_present = True;
1536            di->opd_avma = di->rw_map_avma + foff - di->rw_map_foff;
1537            di->opd_size = size;
1538            TRACE_SYMTAB("acquiring .opd avma = %p\n", di->opd_avma);
1539         } else {
1540            BAD(".opd");
1541         }
1542      }
1543
1544      /* Accept .eh_frame where mapped as rx (code).  This seems to be
1545         the common case.  However, if that doesn't pan out, try for
1546         rw (data) instead. */
1547      if (0 == VG_(strcmp)(name, ".eh_frame")) {
1548         if (inrx && size > 0 && !di->ehframe_present) {
1549            di->ehframe_present = True;
1550            di->ehframe_avma = di->rx_map_avma + foff - di->rx_map_foff;
1551            di->ehframe_size = size;
1552            TRACE_SYMTAB("acquiring .eh_frame avma = %p\n", di->ehframe_avma);
1553         } else
1554         if (inrw && size > 0 && !di->ehframe_present) {
1555            di->ehframe_present = True;
1556            di->ehframe_avma = di->rw_map_avma + foff - di->rw_map_foff;
1557            di->ehframe_size = size;
1558            TRACE_SYMTAB("acquiring .eh_frame avma = %p\n", di->ehframe_avma);
1559         } else {
1560            BAD(".eh_frame");
1561         }
1562      }
1563
1564#    undef BAD
1565
1566   }
1567
1568   /* Kludge: ignore all previous computations for .bss avma range,
1569      and simply assume that .bss immediately follows .data/.sdata.*/
1570   if (1) {
1571      SizeT data_al = round_Addr_upwards(di->data_avma, data_align)
1572                      - di->data_avma;
1573      TRACE_SYMTAB("data_al = %ld\n", data_al);
1574      bss_totsize += data_al;
1575      di->bss_svma = gen_bss_lowest_svma;
1576      di->bss_size = bss_totsize;
1577      di->bss_avma = di->data_avma + (di->bss_svma - di->data_svma);
1578      di->bss_bias = di->data_bias;
1579      TRACE_SYMTAB("kludged .bss svma = %p .. %p\n",
1580                   di->bss_svma, di->bss_svma + di->bss_size - 1);
1581      TRACE_SYMTAB("kludged .bss avma = %p .. %p\n",
1582                   di->bss_avma, di->bss_avma + di->bss_size - 1);
1583      TRACE_SYMTAB("kludged .bss bias = %p\n", di->bss_bias);
1584   }
1585
1586   if (0) VG_(printf)("YYYY text_: avma %p  size %ld  bias %p\n",
1587                      di->text_avma, di->text_size, di->text_bias);
1588
1589   if (VG_(clo_verbosity) > 2 || VG_(clo_trace_redir))
1590      VG_(message)(Vg_DebugMsg, "   svma %010p, avma %010p",
1591                                di->text_avma - di->text_bias,
1592                                di->text_avma );
1593
1594   TRACE_SYMTAB("\n");
1595   TRACE_SYMTAB("------ Finding image addresses "
1596                "for debug-info sections ------\n");
1597
1598   /* Find interesting sections, read the symbol table(s), read any debug
1599      information */
1600   {
1601      /* IMAGE addresses: pointers to start of sections in the
1602         transiently loaded oimage, not in the fragments of the file
1603         mapped in by the guest's dynamic linker. */
1604      UChar*     strtab_img       = NULL; /* .strtab */
1605      ElfXX_Sym* symtab_img       = NULL; /* .symtab */
1606      UChar*     dynstr_img       = NULL; /* .dynstr */
1607      ElfXX_Sym* dynsym_img       = NULL; /* .dynsym */
1608      UChar*     debuglink_img    = NULL; /* .gnu_debuglink */
1609      UChar*     stab_img         = NULL; /* .stab         (stabs)  */
1610      UChar*     stabstr_img      = NULL; /* .stabstr      (stabs)  */
1611      UChar*     debug_line_img   = NULL; /* .debug_line   (dwarf2) */
1612      UChar*     debug_info_img   = NULL; /* .debug_info   (dwarf2) */
1613      UChar*     debug_abbv_img   = NULL; /* .debug_abbrev (dwarf2) */
1614      UChar*     debug_str_img    = NULL; /* .debug_str    (dwarf2) */
1615      UChar*     debug_ranges_img = NULL; /* .debug_ranges (dwarf2) */
1616      UChar*     debug_loc_img    = NULL; /* .debug_loc    (dwarf2) */
1617      UChar*     dwarf1d_img      = NULL; /* .debug        (dwarf1) */
1618      UChar*     dwarf1l_img      = NULL; /* .line         (dwarf1) */
1619      UChar*     ehframe_img      = NULL; /* .eh_frame     (dwarf2) */
1620      UChar*     opd_img          = NULL; /* .opd (dwarf2,
1621                                                   ppc64-linux) */
1622      /* Section sizes, in bytes */
1623      SizeT      strtab_sz       = 0;
1624      SizeT      symtab_sz       = 0;
1625      SizeT      dynstr_sz       = 0;
1626      SizeT      dynsym_sz       = 0;
1627      SizeT      debuglink_sz    = 0;
1628      SizeT      stab_sz         = 0;
1629      SizeT      stabstr_sz      = 0;
1630      SizeT      debug_line_sz   = 0;
1631      SizeT      debug_info_sz   = 0;
1632      SizeT      debug_abbv_sz   = 0;
1633      SizeT      debug_str_sz    = 0;
1634      SizeT      debug_ranges_sz = 0;
1635      SizeT      debug_loc_sz    = 0;
1636      SizeT      dwarf1d_sz      = 0;
1637      SizeT      dwarf1l_sz      = 0;
1638      SizeT      ehframe_sz      = 0;
1639      SizeT      opd_sz_unused   = 0;
1640
1641      /* Find all interesting sections */
1642
1643      /* What FIND does: it finds the section called SEC_NAME.  The
1644         size of it is assigned to SEC_SIZE.  The address of the
1645         section in the transiently loaded oimage is assigned to
1646         SEC_FILEA.  Even for sections which are marked loadable, the
1647         client's ld.so may not have loaded them yet, so there is no
1648         guarantee that we can safely prod around in any such area).
1649         Because the entire object file is transiently mapped aboard
1650         for inspection, it's always safe to inspect that area. */
1651
1652      for (i = 0; i < ehdr_img->e_shnum; i++) {
1653
1654#        define FIND(sec_name, sec_size, sec_img) \
1655         do { ElfXX_Shdr* shdr \
1656                 = INDEX_BIS( shdr_img, i, shdr_ent_szB ); \
1657            if (0 == VG_(strcmp)(sec_name, shdr_strtab_img \
1658                                           + shdr->sh_name)) { \
1659               Bool nobits; \
1660               sec_img  = (void*)(oimage + shdr->sh_offset); \
1661               sec_size = shdr->sh_size; \
1662               nobits   = shdr->sh_type == SHT_NOBITS; \
1663               TRACE_SYMTAB( "%18s:  img %p .. %p\n", \
1664                             sec_name, (UChar*)sec_img, \
1665                             ((UChar*)sec_img) + sec_size - 1); \
1666               /* SHT_NOBITS sections have zero size in the file. */ \
1667               if ( shdr->sh_offset \
1668                    + (nobits ? 0 : sec_size) > n_oimage ) { \
1669                  ML_(symerr)(di, True, \
1670                              "   section beyond image end?!"); \
1671                  goto out; \
1672               } \
1673            } \
1674         } while (0);
1675
1676         /*   NAME              SIZE             IMAGE addr */
1677         FIND(".dynsym",        dynsym_sz,       dynsym_img)
1678         FIND(".dynstr",        dynstr_sz,       dynstr_img)
1679         FIND(".symtab",        symtab_sz,       symtab_img)
1680         FIND(".strtab",        strtab_sz,       strtab_img)
1681
1682         FIND(".gnu_debuglink", debuglink_sz,    debuglink_img)
1683
1684         FIND(".stab",          stab_sz,         stab_img)
1685         FIND(".stabstr",       stabstr_sz,      stabstr_img)
1686
1687         FIND(".debug_line",    debug_line_sz,   debug_line_img)
1688         FIND(".debug_info",    debug_info_sz,   debug_info_img)
1689         FIND(".debug_abbrev",  debug_abbv_sz,   debug_abbv_img)
1690         FIND(".debug_str",     debug_str_sz,    debug_str_img)
1691         FIND(".debug_ranges",  debug_ranges_sz, debug_ranges_img)
1692         FIND(".debug_loc",     debug_loc_sz,    debug_loc_img)
1693
1694         FIND(".debug",         dwarf1d_sz,      dwarf1d_img)
1695         FIND(".line",          dwarf1l_sz,      dwarf1l_img)
1696         FIND(".eh_frame",      ehframe_sz,      ehframe_img)
1697
1698         FIND(".opd",           opd_sz_unused,   opd_img)
1699
1700#        undef FIND
1701      }
1702
1703      /* Did we find a debuglink section? */
1704      if (debuglink_img != NULL) {
1705         UInt crc_offset = VG_ROUNDUP(VG_(strlen)(debuglink_img)+1, 4);
1706         UInt crc;
1707
1708         vg_assert(crc_offset + sizeof(UInt) <= debuglink_sz);
1709
1710         /* Extract the CRC from the debuglink section */
1711         crc = *(UInt *)(debuglink_img + crc_offset);
1712
1713         /* See if we can find a matching debug file */
1714         dimage = find_debug_file( di, di->filename, debuglink_img,
1715                                   crc, &n_dimage );
1716
1717         if (dimage != 0
1718             && n_dimage >= sizeof(ElfXX_Ehdr)
1719             && ML_(is_elf_object_file)((void*)dimage, n_dimage)) {
1720
1721            /* Pull out and validate program header and section header info */
1722            ElfXX_Ehdr* ehdr_dimg     = (ElfXX_Ehdr*)dimage;
1723            ElfXX_Phdr* phdr_dimg     = (ElfXX_Phdr*)( ((UChar*)ehdr_dimg)
1724                                                       + ehdr_dimg->e_phoff );
1725            UWord       phdr_dnent    = ehdr_dimg->e_phnum;
1726            UWord       phdr_dent_szB = ehdr_dimg->e_phentsize;
1727            ElfXX_Shdr* shdr_dimg     = (ElfXX_Shdr*)( ((UChar*)ehdr_dimg)
1728                                                       + ehdr_dimg->e_shoff );
1729            UWord       shdr_dnent       = ehdr_dimg->e_shnum;
1730            UWord       shdr_dent_szB    = ehdr_dimg->e_shentsize;
1731            UChar*      shdr_strtab_dimg = NULL;
1732
1733            Bool need_symtab, need_stabs, need_dwarf2, need_dwarf1;
1734
1735            if (phdr_dnent == 0
1736                || !contained_within(
1737                       dimage, n_dimage,
1738                       (Addr)phdr_dimg, phdr_dnent * phdr_dent_szB)) {
1739               ML_(symerr)(di, True,
1740                           "Missing or invalid ELF Program Header Table"
1741                           " (debuginfo file)");
1742               goto out;
1743            }
1744
1745            if (shdr_dnent == 0
1746                || !contained_within(
1747                       dimage, n_dimage,
1748                       (Addr)shdr_dimg, shdr_dnent * shdr_dent_szB)) {
1749               ML_(symerr)(di, True,
1750                           "Missing or invalid ELF Section Header Table"
1751                           " (debuginfo file)");
1752               goto out;
1753            }
1754
1755            /* Also find the section header's string table, and validate. */
1756            /* checked previously by is_elf_object_file: */
1757            vg_assert( ehdr_dimg->e_shstrndx != SHN_UNDEF );
1758
1759            shdr_strtab_dimg
1760               = (UChar*)( ((UChar*)ehdr_dimg)
1761                           + shdr_dimg[ehdr_dimg->e_shstrndx].sh_offset);
1762            if (!contained_within(
1763                    dimage, n_dimage,
1764                    (Addr)shdr_strtab_dimg,
1765                    1/*bogus, but we don't know the real size*/ )) {
1766               ML_(symerr)(di, True,
1767                           "Invalid ELF Section Header String Table"
1768                           " (debuginfo file)");
1769               goto out;
1770            }
1771
1772            need_symtab = (NULL == symtab_img);
1773            need_stabs  = (NULL == stab_img);
1774            need_dwarf2 = (NULL == debug_info_img);
1775            need_dwarf1 = (NULL == dwarf1d_img);
1776
1777            for (i = 0; i < ehdr_dimg->e_phnum; i++) {
1778               ElfXX_Phdr* phdr
1779                  = INDEX_BIS( (void*)(dimage + ehdr_dimg->e_phoff),
1780                                          i, phdr_ent_szB );
1781               if (phdr->p_type == PT_LOAD) {
1782                  //offset_dimage = di->text_avma - phdr->p_vaddr;
1783                  // FIXME: update di->text_bias at this point?
1784                  // or can we assume the SVMAs in the debuginfo
1785                  // file (hence, the biases) are the same as
1786                  // established from the main file?
1787                  break;
1788               }
1789            }
1790
1791            /* Same deal as previous FIND, except only do it for those
1792               sections for which we didn't find anything useful in
1793               the main file. */
1794
1795            /* Find all interesting sections */
1796            for (i = 0; i < ehdr_dimg->e_shnum; i++) {
1797
1798#              define FIND(condition, sec_name, sec_size, sec_img) \
1799               do { ElfXX_Shdr* shdr \
1800                       = INDEX_BIS( shdr_dimg, i, shdr_dent_szB ); \
1801                  if (condition \
1802                      && 0 == VG_(strcmp)(sec_name, \
1803                                          shdr_strtab_dimg + shdr->sh_name)) { \
1804                     Bool nobits; \
1805                     if (0 != sec_img) \
1806                        VG_(core_panic)("repeated section!\n"); \
1807                     sec_img  = (void*)(dimage + shdr->sh_offset); \
1808                     sec_size = shdr->sh_size; \
1809                     nobits   = shdr->sh_type == SHT_NOBITS; \
1810                     TRACE_SYMTAB( "%18s: dimg %p .. %p\n", \
1811                                   sec_name, \
1812                                   (UChar*)sec_img, \
1813                                   ((UChar*)sec_img) + sec_size - 1); \
1814                     /* SHT_NOBITS sections have zero size in the file. */ \
1815                     if ( shdr->sh_offset \
1816                          + (nobits ? 0 : sec_size) > n_dimage ) { \
1817                        ML_(symerr)(di, True, \
1818                                    "   section beyond image end?!"); \
1819                        goto out; \
1820                     } \
1821                  } \
1822               } while (0);
1823
1824               /* NEEDED?        NAME             SIZE           IMAGE addr */
1825               FIND(need_symtab, ".symtab",       symtab_sz,     symtab_img)
1826               FIND(need_symtab, ".strtab",       strtab_sz,     strtab_img)
1827               FIND(need_stabs,  ".stab",         stab_sz,       stab_img)
1828               FIND(need_stabs,  ".stabstr",      stabstr_sz,    stabstr_img)
1829               FIND(need_dwarf2, ".debug_line",   debug_line_sz, debug_line_img)
1830               FIND(need_dwarf2, ".debug_info",   debug_info_sz, debug_info_img)
1831               FIND(need_dwarf2, ".debug_abbrev", debug_abbv_sz, debug_abbv_img)
1832               FIND(need_dwarf2, ".debug_str",    debug_str_sz,  debug_str_img)
1833               FIND(need_dwarf2, ".debug_ranges", debug_ranges_sz,
1834                                                               debug_ranges_img)
1835               FIND(need_dwarf2, ".debug_loc",    debug_loc_sz,  debug_loc_img)
1836               FIND(need_dwarf1, ".debug",        dwarf1d_sz,    dwarf1d_img)
1837               FIND(need_dwarf1, ".line",         dwarf1l_sz,    dwarf1l_img)
1838
1839#              undef FIND
1840            }
1841         }
1842      }
1843
1844      /* Check some sizes */
1845      vg_assert((dynsym_sz % sizeof(ElfXX_Sym)) == 0);
1846      vg_assert((symtab_sz % sizeof(ElfXX_Sym)) == 0);
1847
1848      /* Read symbols */
1849      {
1850         void (*read_elf_symtab)(struct _DebugInfo*,UChar*,
1851                                 ElfXX_Sym*,SizeT,
1852                                 UChar*,SizeT,
1853                                 UChar*);
1854#        if defined(VGP_ppc64_linux)
1855         read_elf_symtab = read_elf_symtab__ppc64_linux;
1856#        else
1857         read_elf_symtab = read_elf_symtab__normal;
1858#        endif
1859         read_elf_symtab(di, "symbol table",
1860                         symtab_img, symtab_sz,
1861                         strtab_img, strtab_sz,
1862                         opd_img);
1863
1864         read_elf_symtab(di, "dynamic symbol table",
1865                         dynsym_img, dynsym_sz,
1866                         dynstr_img, dynstr_sz,
1867                         opd_img);
1868      }
1869
1870      /* Read .eh_frame (call-frame-info) if any */
1871      if (ehframe_img) {
1872         vg_assert(ehframe_sz == di->ehframe_size);
1873         ML_(read_callframe_info_dwarf3)( di, ehframe_img );
1874      }
1875
1876      /* Read the stabs and/or dwarf2 debug information, if any.  It
1877         appears reading stabs stuff on amd64-linux doesn't work, so
1878         we ignore it. */
1879#     if !defined(VGP_amd64_linux)
1880      if (stab_img && stabstr_img) {
1881         ML_(read_debuginfo_stabs) ( di, di->text_bias, stab_img, stab_sz,
1882                                         stabstr_img, stabstr_sz );
1883      }
1884#     endif
1885      /* jrs 2006-01-01: icc-8.1 has been observed to generate
1886         binaries without debug_str sections.  Don't preclude
1887         debuginfo reading for that reason, but, in
1888         read_unitinfo_dwarf2, do check that debugstr is non-NULL
1889         before using it. */
1890      if (debug_info_img && debug_abbv_img && debug_line_img
1891                                           /* && debug_str_img */) {
1892
1893         /* The old reader: line numbers and unwind info only */
1894         ML_(read_debuginfo_dwarf3) ( di,
1895                                      debug_info_img, debug_info_sz,
1896                                      debug_abbv_img, debug_abbv_sz,
1897                                      debug_line_img, debug_line_sz,
1898                                      debug_str_img,  debug_str_sz );
1899
1900         /* The new reader: read the DIEs in .debug_info to acquire
1901            information on variable types and locations.  But only if
1902            the tool asks for it, or the user requests it on the
1903            command line. */
1904         if (VG_(needs).var_info /* the tool requires it */
1905             || VG_(clo_read_var_info) /* the user asked for it */) {
1906            ML_(new_dwarf3_reader)(
1907               di, debug_info_img,   debug_info_sz,
1908                   debug_abbv_img,   debug_abbv_sz,
1909                   debug_line_img,   debug_line_sz,
1910                   debug_str_img,    debug_str_sz,
1911                   debug_ranges_img, debug_ranges_sz,
1912                   debug_loc_img,    debug_loc_sz
1913            );
1914         }
1915      }
1916      if (dwarf1d_img && dwarf1l_img) {
1917         ML_(read_debuginfo_dwarf1) ( di, dwarf1d_img, dwarf1d_sz,
1918                                          dwarf1l_img, dwarf1l_sz );
1919      }
1920   }
1921   res = True;
1922
1923  out: {
1924   SysRes m_res;
1925
1926   /* Last, but not least, heave the image(s) back overboard. */
1927   if (dimage) {
1928      m_res = VG_(am_munmap_valgrind) ( dimage, n_dimage );
1929      vg_assert(!m_res.isError);
1930   }
1931   m_res = VG_(am_munmap_valgrind) ( oimage, n_oimage );
1932   vg_assert(!m_res.isError);
1933   return res;
1934  }
1935}
1936
1937
1938/*--------------------------------------------------------------------*/
1939/*--- end                                                          ---*/
1940/*--------------------------------------------------------------------*/
1941