readelf.c revision 76d15fa48b28127397368c6cbe33739c33d4d74d
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         if ((!inrw) && (!inrx) && size > 0 && !di->bss_present) {
1397            /* File contains a .bss, but it didn't get mapped.  Ignore. */
1398            di->bss_present = False;
1399            di->bss_svma = 0;
1400            di->bss_avma = 0;
1401            di->bss_size = 0;
1402            di->bss_bias = 0;
1403            bss_align = 0;
1404         } else {
1405            BAD(".bss");
1406         }
1407      }
1408
1409      /* Accept .sbss where mapped as rw (data) */
1410      if (0 == VG_(strcmp)(name, ".sbss")) {
1411         if (inrw && size > 0 && sbss_size == 0) {
1412            bss_totsize += round_Addr_upwards(size, alyn);
1413            if (svma < gen_bss_lowest_svma)
1414               gen_bss_lowest_svma = svma;
1415            TRACE_SYMTAB("increasing total bss-like size to %ld\n",
1416                         bss_totsize);
1417            sbss_size  = size;
1418            sbss_svma  = svma;
1419            sbss_align = alyn;
1420         } else {
1421            BAD(".sbss");
1422         }
1423      }
1424
1425      /* Accept .dynbss where mapped as rw (data) */
1426      if (0 == VG_(strcmp)(name, ".dynbss")) {
1427	if (inrw && size > 0 /* && sbss_size == 0*/) {
1428           bss_totsize += round_Addr_upwards(size, alyn);
1429           if (svma < gen_bss_lowest_svma)
1430              gen_bss_lowest_svma = svma;
1431           TRACE_SYMTAB("increasing total bss-like size to %ld\n",
1432                        bss_totsize);
1433         } else {
1434            BAD(".dynbss");
1435         }
1436      }
1437
1438      /* Accept .got where mapped as rw (data) */
1439      if (0 == VG_(strcmp)(name, ".got")) {
1440         if (inrw && size > 0 && !di->got_present) {
1441            di->got_present = True;
1442            di->got_avma = di->rw_map_avma + foff - di->rw_map_foff;
1443            di->got_size = size;
1444            TRACE_SYMTAB("acquiring .got avma = %p\n", di->got_avma);
1445         } else {
1446            BAD(".got");
1447         }
1448      }
1449
1450      /* PLT is different on different platforms, it seems. */
1451#     if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
1452      /* Accept .plt where mapped as rx (code) */
1453      if (0 == VG_(strcmp)(name, ".plt")) {
1454         if (inrx && size > 0 && !di->plt_present) {
1455            di->plt_present = True;
1456            di->plt_avma = di->rx_map_avma + foff - di->rx_map_foff;
1457            di->plt_size = size;
1458            TRACE_SYMTAB("acquiring .plt avma = %p\n", di->plt_avma);
1459         } else {
1460            BAD(".plt");
1461         }
1462      }
1463#     elif defined(VGP_ppc32_linux)
1464      /* Accept .plt where mapped as rw (data) */
1465      if (0 == VG_(strcmp)(name, ".plt")) {
1466         if (inrw && size > 0 && !di->plt_present) {
1467            di->plt_present = True;
1468            di->plt_avma = di->rw_map_avma + foff - di->rw_map_foff;
1469            di->plt_size = size;
1470            TRACE_SYMTAB("acquiring .plt avma = %p\n", di->plt_avma);
1471         } else {
1472            BAD(".plt");
1473         }
1474      }
1475#     elif defined(VGP_ppc64_linux)
1476      /* Accept .plt where mapped as rw (data), or unmapped */
1477      if (0 == VG_(strcmp)(name, ".plt")) {
1478         if (inrw && size > 0 && !di->plt_present) {
1479            di->plt_present = True;
1480            di->plt_avma = di->rw_map_avma + foff - di->rw_map_foff;
1481            di->plt_size = size;
1482            TRACE_SYMTAB("acquiring .plt avma = %p\n", di->plt_avma);
1483         } else
1484         if ((!inrw) && (!inrx) && size > 0 && !di->plt_present) {
1485            /* File contains a .plt, but it didn't get mapped.
1486               Presumably it is not required on this platform.  At
1487               least don't reject the situation as invalid. */
1488            di->plt_present = True;
1489            di->plt_avma = 0;
1490            di->plt_size = 0;
1491         } else {
1492            BAD(".plt");
1493         }
1494      }
1495#     else
1496#       error "Unsupported platform"
1497#     endif
1498
1499      /* Accept .opd where mapped as rw (data) */
1500      if (0 == VG_(strcmp)(name, ".opd")) {
1501         if (inrw && size > 0 && !di->opd_present) {
1502            di->opd_present = True;
1503            di->opd_avma = di->rw_map_avma + foff - di->rw_map_foff;
1504            di->opd_size = size;
1505            TRACE_SYMTAB("acquiring .opd avma = %p\n", di->opd_avma);
1506         } else {
1507            BAD(".opd");
1508         }
1509      }
1510
1511      /* Accept .eh_frame where mapped as rx (code).  This seems to be
1512         the common case.  However, if that doesn't pan out, try for
1513         rw (data) instead. */
1514      if (0 == VG_(strcmp)(name, ".eh_frame")) {
1515         if (inrx && size > 0 && !di->ehframe_present) {
1516            di->ehframe_present = True;
1517            di->ehframe_avma = di->rx_map_avma + foff - di->rx_map_foff;
1518            di->ehframe_size = size;
1519            TRACE_SYMTAB("acquiring .eh_frame avma = %p\n", di->ehframe_avma);
1520         } else
1521         if (inrw && size > 0 && !di->ehframe_present) {
1522            di->ehframe_present = True;
1523            di->ehframe_avma = di->rw_map_avma + foff - di->rw_map_foff;
1524            di->ehframe_size = size;
1525            TRACE_SYMTAB("acquiring .eh_frame avma = %p\n", di->ehframe_avma);
1526         } else {
1527            BAD(".eh_frame");
1528         }
1529      }
1530
1531#    undef BAD
1532
1533   }
1534
1535   /* Kludge: ignore all previous computations for .bss avma range,
1536      and simply assume that .bss immediately follows .data/.sdata.*/
1537   if (1) {
1538      SizeT data_al = round_Addr_upwards(di->data_avma, data_align)
1539                      - di->data_avma;
1540      TRACE_SYMTAB("data_al = %ld\n", data_al);
1541      bss_totsize += data_al;
1542      di->bss_svma = gen_bss_lowest_svma;
1543      di->bss_size = bss_totsize;
1544      di->bss_avma = di->data_avma + (di->bss_svma - di->data_svma);
1545      di->bss_bias = di->data_bias;
1546      TRACE_SYMTAB("kludged .bss svma = %p .. %p\n",
1547                   di->bss_svma, di->bss_svma + di->bss_size - 1);
1548      TRACE_SYMTAB("kludged .bss avma = %p .. %p\n",
1549                   di->bss_avma, di->bss_avma + di->bss_size - 1);
1550      TRACE_SYMTAB("kludged .bss bias = %p\n", di->bss_bias);
1551   }
1552
1553   if (0) VG_(printf)("YYYY text_: avma %p  size %ld  bias %p\n",
1554                      di->text_avma, di->text_size, di->text_bias);
1555
1556   if (VG_(clo_verbosity) > 2 || VG_(clo_trace_redir))
1557      VG_(message)(Vg_DebugMsg, "   svma %010p, avma %010p",
1558                                di->text_avma - di->text_bias,
1559                                di->text_avma );
1560
1561   TRACE_SYMTAB("\n");
1562   TRACE_SYMTAB("------ Finding image addresses "
1563                "for debug-info sections ------\n");
1564
1565   /* Find interesting sections, read the symbol table(s), read any debug
1566      information */
1567   {
1568      /* IMAGE addresses: pointers to start of sections in the
1569         transiently loaded oimage, not in the fragments of the file
1570         mapped in by the guest's dynamic linker. */
1571      UChar*     strtab_img       = NULL; /* .strtab */
1572      ElfXX_Sym* symtab_img       = NULL; /* .symtab */
1573      UChar*     dynstr_img       = NULL; /* .dynstr */
1574      ElfXX_Sym* dynsym_img       = NULL; /* .dynsym */
1575      UChar*     debuglink_img    = NULL; /* .gnu_debuglink */
1576      UChar*     stab_img         = NULL; /* .stab         (stabs)  */
1577      UChar*     stabstr_img      = NULL; /* .stabstr      (stabs)  */
1578      UChar*     debug_line_img   = NULL; /* .debug_line   (dwarf2) */
1579      UChar*     debug_info_img   = NULL; /* .debug_info   (dwarf2) */
1580      UChar*     debug_abbv_img   = NULL; /* .debug_abbrev (dwarf2) */
1581      UChar*     debug_str_img    = NULL; /* .debug_str    (dwarf2) */
1582      UChar*     debug_ranges_img = NULL; /* .debug_ranges (dwarf2) */
1583      UChar*     debug_loc_img    = NULL; /* .debug_loc    (dwarf2) */
1584      UChar*     dwarf1d_img      = NULL; /* .debug        (dwarf1) */
1585      UChar*     dwarf1l_img      = NULL; /* .line         (dwarf1) */
1586      UChar*     ehframe_img      = NULL; /* .eh_frame     (dwarf2) */
1587      UChar*     opd_img          = NULL; /* .opd (dwarf2,
1588                                                   ppc64-linux) */
1589      /* Section sizes, in bytes */
1590      SizeT      strtab_sz       = 0;
1591      SizeT      symtab_sz       = 0;
1592      SizeT      dynstr_sz       = 0;
1593      SizeT      dynsym_sz       = 0;
1594      SizeT      debuglink_sz    = 0;
1595      SizeT      stab_sz         = 0;
1596      SizeT      stabstr_sz      = 0;
1597      SizeT      debug_line_sz   = 0;
1598      SizeT      debug_info_sz   = 0;
1599      SizeT      debug_abbv_sz   = 0;
1600      SizeT      debug_str_sz    = 0;
1601      SizeT      debug_ranges_sz = 0;
1602      SizeT      debug_loc_sz    = 0;
1603      SizeT      dwarf1d_sz      = 0;
1604      SizeT      dwarf1l_sz      = 0;
1605      SizeT      ehframe_sz      = 0;
1606      SizeT      opd_sz_unused   = 0;
1607
1608      /* Find all interesting sections */
1609
1610      /* What FIND does: it finds the section called SEC_NAME.  The
1611         size of it is assigned to SEC_SIZE.  The address of the
1612         section in the transiently loaded oimage is assigned to
1613         SEC_FILEA.  Even for sections which are marked loadable, the
1614         client's ld.so may not have loaded them yet, so there is no
1615         guarantee that we can safely prod around in any such area).
1616         Because the entire object file is transiently mapped aboard
1617         for inspection, it's always safe to inspect that area. */
1618
1619      for (i = 0; i < ehdr_img->e_shnum; i++) {
1620
1621#        define FIND(sec_name, sec_size, sec_img) \
1622         do { ElfXX_Shdr* shdr \
1623                 = INDEX_BIS( shdr_img, i, shdr_ent_szB ); \
1624            if (0 == VG_(strcmp)(sec_name, shdr_strtab_img \
1625                                           + shdr->sh_name)) { \
1626               Bool nobits; \
1627               sec_img  = (void*)(oimage + shdr->sh_offset); \
1628               sec_size = shdr->sh_size; \
1629               nobits   = shdr->sh_type == SHT_NOBITS; \
1630               TRACE_SYMTAB( "%18s:  img %p .. %p\n", \
1631                             sec_name, (UChar*)sec_img, \
1632                             ((UChar*)sec_img) + sec_size - 1); \
1633               /* SHT_NOBITS sections have zero size in the file. */ \
1634               if ( shdr->sh_offset \
1635                    + (nobits ? 0 : sec_size) > n_oimage ) { \
1636                  ML_(symerr)(di, True, \
1637                              "   section beyond image end?!"); \
1638                  goto out; \
1639               } \
1640            } \
1641         } while (0);
1642
1643         /*   NAME              SIZE             IMAGE addr */
1644         FIND(".dynsym",        dynsym_sz,       dynsym_img)
1645         FIND(".dynstr",        dynstr_sz,       dynstr_img)
1646         FIND(".symtab",        symtab_sz,       symtab_img)
1647         FIND(".strtab",        strtab_sz,       strtab_img)
1648
1649         FIND(".gnu_debuglink", debuglink_sz,    debuglink_img)
1650
1651         FIND(".stab",          stab_sz,         stab_img)
1652         FIND(".stabstr",       stabstr_sz,      stabstr_img)
1653
1654         FIND(".debug_line",    debug_line_sz,   debug_line_img)
1655         FIND(".debug_info",    debug_info_sz,   debug_info_img)
1656         FIND(".debug_abbrev",  debug_abbv_sz,   debug_abbv_img)
1657         FIND(".debug_str",     debug_str_sz,    debug_str_img)
1658         FIND(".debug_ranges",  debug_ranges_sz, debug_ranges_img)
1659         FIND(".debug_loc",     debug_loc_sz,    debug_loc_img)
1660
1661         FIND(".debug",         dwarf1d_sz,      dwarf1d_img)
1662         FIND(".line",          dwarf1l_sz,      dwarf1l_img)
1663         FIND(".eh_frame",      ehframe_sz,      ehframe_img)
1664
1665         FIND(".opd",           opd_sz_unused,   opd_img)
1666
1667#        undef FIND
1668      }
1669
1670      /* Did we find a debuglink section? */
1671      if (debuglink_img != NULL) {
1672         UInt crc_offset = VG_ROUNDUP(VG_(strlen)(debuglink_img)+1, 4);
1673         UInt crc;
1674
1675         vg_assert(crc_offset + sizeof(UInt) <= debuglink_sz);
1676
1677         /* Extract the CRC from the debuglink section */
1678         crc = *(UInt *)(debuglink_img + crc_offset);
1679
1680         /* See if we can find a matching debug file */
1681         dimage = find_debug_file( di, di->filename, debuglink_img,
1682                                   crc, &n_dimage );
1683
1684         if (dimage != 0
1685             && n_dimage >= sizeof(ElfXX_Ehdr)
1686             && ML_(is_elf_object_file)((void*)dimage, n_dimage)) {
1687
1688            /* Pull out and validate program header and section header info */
1689            ElfXX_Ehdr* ehdr_dimg     = (ElfXX_Ehdr*)dimage;
1690            ElfXX_Phdr* phdr_dimg     = (ElfXX_Phdr*)( ((UChar*)ehdr_dimg)
1691                                                       + ehdr_dimg->e_phoff );
1692            UWord       phdr_dnent    = ehdr_dimg->e_phnum;
1693            UWord       phdr_dent_szB = ehdr_dimg->e_phentsize;
1694            ElfXX_Shdr* shdr_dimg     = (ElfXX_Shdr*)( ((UChar*)ehdr_dimg)
1695                                                       + ehdr_dimg->e_shoff );
1696            UWord       shdr_dnent       = ehdr_dimg->e_shnum;
1697            UWord       shdr_dent_szB    = ehdr_dimg->e_shentsize;
1698            UChar*      shdr_strtab_dimg = NULL;
1699
1700            Bool need_symtab, need_stabs, need_dwarf2, need_dwarf1;
1701
1702            if (phdr_dnent == 0
1703                || !contained_within(
1704                       dimage, n_dimage,
1705                       (Addr)phdr_dimg, phdr_dnent * phdr_dent_szB)) {
1706               ML_(symerr)(di, True,
1707                           "Missing or invalid ELF Program Header Table"
1708                           " (debuginfo file)");
1709               goto out;
1710            }
1711
1712            if (shdr_dnent == 0
1713                || !contained_within(
1714                       dimage, n_dimage,
1715                       (Addr)shdr_dimg, shdr_dnent * shdr_dent_szB)) {
1716               ML_(symerr)(di, True,
1717                           "Missing or invalid ELF Section Header Table"
1718                           " (debuginfo file)");
1719               goto out;
1720            }
1721
1722            /* Also find the section header's string table, and validate. */
1723            /* checked previously by is_elf_object_file: */
1724            vg_assert( ehdr_dimg->e_shstrndx != SHN_UNDEF );
1725
1726            shdr_strtab_dimg
1727               = (UChar*)( ((UChar*)ehdr_dimg)
1728                           + shdr_dimg[ehdr_dimg->e_shstrndx].sh_offset);
1729            if (!contained_within(
1730                    dimage, n_dimage,
1731                    (Addr)shdr_strtab_dimg,
1732                    1/*bogus, but we don't know the real size*/ )) {
1733               ML_(symerr)(di, True,
1734                           "Invalid ELF Section Header String Table"
1735                           " (debuginfo file)");
1736               goto out;
1737            }
1738
1739            need_symtab = (NULL == symtab_img);
1740            need_stabs  = (NULL == stab_img);
1741            need_dwarf2 = (NULL == debug_info_img);
1742            need_dwarf1 = (NULL == dwarf1d_img);
1743
1744            for (i = 0; i < ehdr_dimg->e_phnum; i++) {
1745               ElfXX_Phdr* phdr
1746                  = INDEX_BIS( (void*)(dimage + ehdr_dimg->e_phoff),
1747                                          i, phdr_ent_szB );
1748               if (phdr->p_type == PT_LOAD) {
1749                  //offset_dimage = di->text_avma - phdr->p_vaddr;
1750                  // FIXME: update di->text_bias at this point?
1751                  // or can we assume the SVMAs in the debuginfo
1752                  // file (hence, the biases) are the same as
1753                  // established from the main file?
1754                  break;
1755               }
1756            }
1757
1758            /* Same deal as previous FIND, except only do it for those
1759               sections for which we didn't find anything useful in
1760               the main file. */
1761
1762            /* Find all interesting sections */
1763            for (i = 0; i < ehdr_dimg->e_shnum; i++) {
1764
1765#              define FIND(condition, sec_name, sec_size, sec_img) \
1766               do { ElfXX_Shdr* shdr \
1767                       = INDEX_BIS( shdr_dimg, i, shdr_dent_szB ); \
1768                  if (condition \
1769                      && 0 == VG_(strcmp)(sec_name, \
1770                                          shdr_strtab_dimg + shdr->sh_name)) { \
1771                     Bool nobits; \
1772                     if (0 != sec_img) \
1773                        VG_(core_panic)("repeated section!\n"); \
1774                     sec_img  = (void*)(dimage + shdr->sh_offset); \
1775                     sec_size = shdr->sh_size; \
1776                     nobits   = shdr->sh_type == SHT_NOBITS; \
1777                     TRACE_SYMTAB( "%18s: dimg %p .. %p\n", \
1778                                   sec_name, \
1779                                   (UChar*)sec_img, \
1780                                   ((UChar*)sec_img) + sec_size - 1); \
1781                     /* SHT_NOBITS sections have zero size in the file. */ \
1782                     if ( shdr->sh_offset \
1783                          + (nobits ? 0 : sec_size) > n_dimage ) { \
1784                        ML_(symerr)(di, True, \
1785                                    "   section beyond image end?!"); \
1786                        goto out; \
1787                     } \
1788                  } \
1789               } while (0);
1790
1791               /* NEEDED?        NAME             SIZE           IMAGE addr */
1792               FIND(need_symtab, ".symtab",       symtab_sz,     symtab_img)
1793               FIND(need_symtab, ".strtab",       strtab_sz,     strtab_img)
1794               FIND(need_stabs,  ".stab",         stab_sz,       stab_img)
1795               FIND(need_stabs,  ".stabstr",      stabstr_sz,    stabstr_img)
1796               FIND(need_dwarf2, ".debug_line",   debug_line_sz, debug_line_img)
1797               FIND(need_dwarf2, ".debug_info",   debug_info_sz, debug_info_img)
1798               FIND(need_dwarf2, ".debug_abbrev", debug_abbv_sz, debug_abbv_img)
1799               FIND(need_dwarf2, ".debug_str",    debug_str_sz,  debug_str_img)
1800               FIND(need_dwarf2, ".debug_ranges", debug_ranges_sz,
1801                                                               debug_ranges_img)
1802               FIND(need_dwarf2, ".debug_loc",    debug_loc_sz,  debug_loc_img)
1803               FIND(need_dwarf1, ".debug",        dwarf1d_sz,    dwarf1d_img)
1804               FIND(need_dwarf1, ".line",         dwarf1l_sz,    dwarf1l_img)
1805
1806#              undef FIND
1807            }
1808         }
1809      }
1810
1811      /* Check some sizes */
1812      vg_assert((dynsym_sz % sizeof(ElfXX_Sym)) == 0);
1813      vg_assert((symtab_sz % sizeof(ElfXX_Sym)) == 0);
1814
1815      /* Read symbols */
1816      {
1817         void (*read_elf_symtab)(struct _DebugInfo*,UChar*,
1818                                 ElfXX_Sym*,SizeT,
1819                                 UChar*,SizeT,
1820                                 UChar*);
1821#        if defined(VGP_ppc64_linux)
1822         read_elf_symtab = read_elf_symtab__ppc64_linux;
1823#        else
1824         read_elf_symtab = read_elf_symtab__normal;
1825#        endif
1826         read_elf_symtab(di, "symbol table",
1827                         symtab_img, symtab_sz,
1828                         strtab_img, strtab_sz,
1829                         opd_img);
1830
1831         read_elf_symtab(di, "dynamic symbol table",
1832                         dynsym_img, dynsym_sz,
1833                         dynstr_img, dynstr_sz,
1834                         opd_img);
1835      }
1836
1837      /* Read .eh_frame (call-frame-info) if any */
1838      if (ehframe_img) {
1839         vg_assert(ehframe_sz == di->ehframe_size);
1840         ML_(read_callframe_info_dwarf3)( di, ehframe_img );
1841      }
1842
1843      /* Read the stabs and/or dwarf2 debug information, if any.  It
1844         appears reading stabs stuff on amd64-linux doesn't work, so
1845         we ignore it. */
1846#     if !defined(VGP_amd64_linux)
1847      if (stab_img && stabstr_img) {
1848         ML_(read_debuginfo_stabs) ( di, di->text_bias, stab_img, stab_sz,
1849                                         stabstr_img, stabstr_sz );
1850      }
1851#     endif
1852      /* jrs 2006-01-01: icc-8.1 has been observed to generate
1853         binaries without debug_str sections.  Don't preclude
1854         debuginfo reading for that reason, but, in
1855         read_unitinfo_dwarf2, do check that debugstr is non-NULL
1856         before using it. */
1857      if (debug_info_img && debug_abbv_img && debug_line_img
1858                                           /* && debug_str_img */) {
1859
1860         /* The old reader: line numbers and unwind info only */
1861         ML_(read_debuginfo_dwarf3) ( di,
1862                                      debug_info_img, debug_info_sz,
1863                                      debug_abbv_img, debug_abbv_sz,
1864                                      debug_line_img, debug_line_sz,
1865                                      debug_str_img,  debug_str_sz );
1866
1867         /* The new reader: read the DIEs in .debug_info to acquire
1868            information on variable types and locations.  But only if
1869            the tool asks for it, or the user requests it on the
1870            command line. */
1871         if (VG_(needs).var_info /* the tool requires it */
1872             || VG_(clo_read_var_info) /* the user asked for it */) {
1873            ML_(new_dwarf3_reader)(
1874               di, debug_info_img,   debug_info_sz,
1875                   debug_abbv_img,   debug_abbv_sz,
1876                   debug_line_img,   debug_line_sz,
1877                   debug_str_img,    debug_str_sz,
1878                   debug_ranges_img, debug_ranges_sz,
1879                   debug_loc_img,    debug_loc_sz
1880            );
1881         }
1882      }
1883      if (dwarf1d_img && dwarf1l_img) {
1884         ML_(read_debuginfo_dwarf1) ( di, dwarf1d_img, dwarf1d_sz,
1885                                          dwarf1l_img, dwarf1l_sz );
1886      }
1887   }
1888   res = True;
1889
1890  out: {
1891   SysRes m_res;
1892
1893   /* Last, but not least, heave the image(s) back overboard. */
1894   if (dimage) {
1895      m_res = VG_(am_munmap_valgrind) ( dimage, n_dimage );
1896      vg_assert(!m_res.isError);
1897   }
1898   m_res = VG_(am_munmap_valgrind) ( oimage, n_oimage );
1899   vg_assert(!m_res.isError);
1900   return res;
1901  }
1902}
1903
1904
1905/*--------------------------------------------------------------------*/
1906/*--- end                                                          ---*/
1907/*--------------------------------------------------------------------*/
1908